Greetings Programs!
I have used the following to remove the table prefixes for all versions up to 9 (.Net Core + Angular) with no issues.
modelBuilder.ChangeAbpTablePrefix<Tenant, Role, User>("");
In v10, with a clean install, I had to change the Target Framework to .NET 5.0 in order to run.
I successfully executed update-database to create the initial tables.
When I went to change the table prefix with the line above, I received the error below.
Is there any additional configuration I need to make for v10?
Thanks,
Wg
System.InvalidOperationException: Both 'TenantFeatureSetting' and 'EditionFeatureSetting' are mapped to the table 'AbpFeatures'. All the entity types in a hierarchy that don't have a discriminator must be mapped to different tables. See https://go.microsoft.com/fwlink/?linkid=2130430 for more information.
at Microsoft.EntityFrameworkCore.Infrastructure.RelationalModelValidator.ValidateTPTMapping(IEntityType rootEntityType, Boolean forTables)
at Microsoft.EntityFrameworkCore.Infrastructure.RelationalModelValidator.ValidateInheritanceMapping(IModel model, IDiagnosticsLogger`1 logger)
at Microsoft.EntityFrameworkCore.Infrastructure.ModelValidator.Validate(IModel model, IDiagnosticsLogger`1 logger)
at Microsoft.EntityFrameworkCore.Infrastructure.RelationalModelValidator.Validate(IModel model, IDiagnosticsLogger`1 logger)
at Microsoft.EntityFrameworkCore.SqlServer.Internal.SqlServerModelValidator.Validate(IModel model, IDiagnosticsLogger`1 logger)
at Microsoft.EntityFrameworkCore.Metadata.Conventions.ValidatingConvention.ProcessModelFinalized(IModel model)
at Microsoft.EntityFrameworkCore.Metadata.Conventions.Internal.ConventionDispatcher.ImmediateConventionScope.OnModelFinalized(IModel model)
at Microsoft.EntityFrameworkCore.Metadata.Conventions.Internal.ConventionDispatcher.OnModelFinalized(IModel model)
at Microsoft.EntityFrameworkCore.Metadata.Internal.Model.FinalizeModel()
at Microsoft.EntityFrameworkCore.ModelBuilder.FinalizeModel()
at Microsoft.EntityFrameworkCore.Infrastructure.ModelSource.CreateModel(DbContext context, IConventionSetBuilder conventionSetBuilder, ModelDependencies modelDependencies)
at Microsoft.EntityFrameworkCore.Infrastructure.ModelSource.GetModel(DbContext context, IConventionSetBuilder conventionSetBuilder, ModelDependencies modelDependencies)
at Microsoft.EntityFrameworkCore.Internal.DbContextServices.CreateModel()
at Microsoft.EntityFrameworkCore.Internal.DbContextServices.get_Model()
at Microsoft.EntityFrameworkCore.Infrastructure.EntityFrameworkServicesBuilder.<>c.<TryAddCoreServices>b__7_3(IServiceProvider p)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitFactory(FactoryCallSite factoryCallSite, RuntimeResolverContext context)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite singletonCallSite, RuntimeResolverContext context)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite singletonCallSite, RuntimeResolverContext context)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.Resolve(ServiceCallSite callSite, ServiceProviderEngineScope scope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.DynamicServiceProviderEngine.<>c__DisplayClass1_0.<RealizeService>b__0(ServiceProviderEngineScope scope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
at Microsoft.EntityFrameworkCore.DbContext.get_DbContextDependencies()
at Microsoft.EntityFrameworkCore.DbContext.get_InternalServiceProvider()
at Microsoft.EntityFrameworkCore.DbContext.Microsoft.EntityFrameworkCore.Infrastructure.IInfrastructure<System.IServiceProvider>.get_Instance()
at Microsoft.EntityFrameworkCore.Infrastructure.Internal.InfrastructureExtensions.GetService[TService](IInfrastructure`1 accessor)
at Microsoft.EntityFrameworkCore.Infrastructure.AccessorExtensions.GetService[TService](IInfrastructure`1 accessor)
at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.CreateContext(Func`1 factory)
at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.CreateContext(String contextType)
at Microsoft.EntityFrameworkCore.Design.Internal.MigrationsOperations.AddMigration(String name, String outputDir, String contextType, String namespace)
at Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigrationImpl(String name, String outputDir, String contextType, String namespace)
at Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigration.<>c__DisplayClass0_0.<.ctor>b__0()
at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.<>c__DisplayClass3_0`1.<Execute>b__0()
at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)
Both 'TenantFeatureSetting' and 'EditionFeatureSetting' are mapped to the table 'AbpFeatures'. All the entity types in a hierarchy that don't have a discriminator must be mapped to different tables. See https://go.microsoft.com/fwlink/?linkid=2130430 for more information.
Hi @maliming,
Yes, thanks,
Wg
Hi @maliming,
I was updating entites (that implemented IMustHaveTenant) prior to sending the notification and I found that I needed to call CurrentUnitOfWork.SaveChangesAsync() before sending the notification.
Thanks,
Wg
Hi @maliming,
Version 8.5.0.
Here is the full class; I create a new list of Abp.UserIdentifier(tenant, userId) and there are values for the parameters being passed to PublishAsync.
Thanks,
Wg
public class UserNotificationAppService : WizgodIncAppServiceBase, IUserNotificationAppService
{
private readonly INotificationPublisher _notificationPublisher;
private readonly IUserAppService _userAppService;
private readonly ITimeSheetApproversAppService _timeSheetApproversAppService;
public UserNotificationAppService(INotificationPublisher notificationPublisher,
IUserAppService userAppService,
ITimeSheetApproversAppService timeSheetApproversAppService)
{
_notificationPublisher = notificationPublisher;
_userAppService = userAppService;
_timeSheetApproversAppService = timeSheetApproversAppService;
}
[AbpAllowAnonymous]
public virtual async Task SendNotificationToApprovers(long fromUserId, string url, string message, string notificationName, int severity)
{
var user = await _userAppService.GetUser(new EntityDto<long> {Id = fromUserId});
if (!user.TimeSheetApproversId.HasValue) return;
var timeSheetApprovers =
await _timeSheetApproversAppService.GetTimeSheetApprovers(
new EntityDto {Id = user.TimeSheetApproversId.Value});
var approverIds = new List<long?> { timeSheetApprovers.ApproverId };
if (timeSheetApprovers.FirstBackupApproverId.HasValue) approverIds.Add(timeSheetApprovers.FirstBackupApproverId.Value);
if (timeSheetApprovers.SecondBackupApproverId.HasValue) approverIds.Add(timeSheetApprovers.SecondBackupApproverId.Value);
var userIds = approverIds.Select(q => new Abp.UserIdentifier(2, q.Value)).ToArray();
message = message.Replace("[Name]", user.Name)
.Replace("[Surname]", user.Surname)
.Replace("[EmployeeID]", user.EmployeeId);
var data = new MessageNotificationData(message) {["url"] = url};
await _notificationPublisher.PublishAsync(notificationName, data, null,(NotificationSeverity)severity, userIds);
}
[AbpAllowAnonymous]
public virtual async Task SendNotificationToUser(long fromUserId, string url, string message, string notificationName, int notificationServerity, long userId)
{
await SendNotificationToUsers(fromUserId, url, message, notificationName, notificationServerity, new[] { userId });
}
[AbpAllowAnonymous]
public virtual async Task SendNotificationToUsers(long fromUserId, string url, string message, string notificationName, int severity, long[] userIds)
{
var user = await UserManager.GetUserByIdAsync(fromUserId);
var userIdentifiers = userIds.Select(q => new Abp.UserIdentifier(2, q)).ToArray();
message = message.Replace("[Name]", user.Name)
.Replace("[Surname]", user.Surname)
.Replace("[EmployeeID]", user.EmployeeId);
var data = new MessageNotificationData(message) {["url"] = url};
await _notificationPublisher.PublishAsync(notificationName, data, severity: (NotificationSeverity)severity, userIds: userIdentifiers);
}
}
Greetings Programs!
When I execute this code: <br>
var userIds = approverIds.Select(q => new Abp.UserIdentifier(2, q.Value)).ToArray();
message = message.Replace("[Name]", user.Name)
.Replace("[Surname]", user.Surname)
.Replace("[EmployeeID]", user.EmployeeId);
var data = new MessageNotificationData(message) {["url"] = url};
await _notificationPublisher.PublishAsync(notificationName, data, null,(NotificationSeverity)severity, userIds);
<br> I am receiving the following error:
ERROR 2020-04-22 16:58:30,000 [8 ] Mvc.ExceptionHandling.AbpExceptionFilter - Can not set TenantId to 0 for IMustHaveTenant entities! Abp.AbpException: Can not set TenantId to 0 for IMustHaveTenant entities! at Abp.EntityFrameworkCore.AbpDbContext.CheckAndSetMustHaveTenantIdProperty(Object entityAsObj) at Abp.EntityFrameworkCore.AbpDbContext.ApplyAbpConceptsForAddedEntity(EntityEntry entry, Nullable`1 userId, EntityChangeReport changeReport) at Abp.EntityFrameworkCore.AbpDbContext.ApplyAbpConcepts(EntityEntry entry, Nullable`1 userId, EntityChangeReport changeReport) at Abp.EntityFrameworkCore.AbpDbContext.ApplyAbpConcepts() at Abp.EntityFrameworkCore.AbpDbContext.SaveChangesAsync(CancellationToken cancellationToken) at Abp.Zero.EntityFrameworkCore.AbpZeroCommonDbContext`3.SaveChangesAsync(CancellationToken cancellationToken) at Abp.EntityFrameworkCore.Uow.EfCoreUnitOfWork.SaveChangesInDbContextAsync(DbContext dbContext) at Abp.EntityFrameworkCore.Uow.EfCoreUnitOfWork.SaveChangesAsync() at Abp.Notifications.NotificationStore.InsertNotificationAsync(NotificationInfo notification) at Abp.Domain.Uow.UnitOfWorkInterceptor.InternalInterceptAsynchronous(IInvocation invocation) at Abp.Notifications.NotificationPublisher.PublishAsync(String notificationName, NotificationData data, EntityIdentifier entityIdentifier, NotificationSeverity severity, UserIdentifier[] userIds, UserIdentifier[] excludedUserIds, Nullable`1[] tenantIds)
Thanks,
Wg
@ismcagdas, I've figured it out; it was an oversight on my part.
When I was migrating the users, I was setting the new NormalizedUserName column with UPPER(Name + ' ' + Surname) instead of UPPER(UserName).
Thanks,
Wg
Hi @ismcagdas,
Has that method changed for 8.5.0?
It's saying that _passwordHasher is not accessable because it's private.
Thanks,
Wg
Hi @ismcagdas,
Will do. I'll let you know in about 10 days; tied up till then.
Thanks,
Wg
Hi @ismcagdas,
I added that code and overrode the method in LogInManager.
At:
var user = await UserManager.FindByNameOrEmailAsync(tenantId, userNameOrEmailAddress);
When it's null,it trys to create the object and the "Email is already taken" exception is thrown at:
await UserManager.CreateAsync(user);
Hi @ismcagdas,
Abp and Abp.* packages are v5.4.0 with Abp.AspNetZeroCore and Abp.AspNetZeroCore.Web being v2.0.0.