- ABP Framework version: v9.0.4
- UI Type: Angular
- Database System: EF Core SQL Server
- Tiered: Yes
- Exception message and full stack trace:
The entity type 'IdentityUserLogin' requires a primary key to be defined. If you intended to use a keyless entity type, call 'HasNoKey' in 'OnModelCreating'. For more information on keyless entity types, see https://go.microsoft.com/fwlink/?linkid=2141943.
System.InvalidOperationException: The entity type 'IdentityUserLogin' requires a primary key to be defined. If you intended to use a keyless entity type, call 'HasNoKey' in 'OnModelCreating'. For more information on keyless entity types, see https://go.microsoft.com/fwlink/?linkid=2141943.
at Microsoft.EntityFrameworkCore.Infrastructure.ModelValidator.ValidateNonNullPrimaryKeys(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.Infrastructure.Internal.SqlServerModelValidator.Validate(IModel model, IDiagnosticsLogger`1 logger)
at Microsoft.EntityFrameworkCore.Infrastructure.ModelRuntimeInitializer.Initialize(IModel model, Boolean designTime, IDiagnosticsLogger`1 validationLogger)
at Microsoft.EntityFrameworkCore.Infrastructure.ModelSource.GetModel(DbContext context, ModelCreationDependencies modelCreationDependencies, Boolean designTime)
at Microsoft.EntityFrameworkCore.Internal.DbContextServices.CreateModel(Boolean designTime)
at Microsoft.EntityFrameworkCore.Internal.DbContextServices.get_Model()
at Microsoft.EntityFrameworkCore.Infrastructure.EntityFrameworkServicesBuilder.<>c.<TryAddCoreServices>b__8_4(IServiceProvider p)
at ResolveService(ILEmitResolverBuilderRuntimeContext, ServiceProviderEngineScope)
at ResolveService(ILEmitResolverBuilderRuntimeContext, ServiceProviderEngineScope)
at ResolveService(ILEmitResolverBuilderRuntimeContext, ServiceProviderEngineScope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
at Volo.Abp.EntityFrameworkCore.AbpDbContextOptionsExtension.<>c__DisplayClass0_0.<ApplyServices>b__1(IServiceProvider provider)
at ResolveService(ILEmitResolverBuilderRuntimeContext, ServiceProviderEngineScope)
at ResolveService(ILEmitResolverBuilderRuntimeContext, ServiceProviderEngineScope)
at ResolveService(ILEmitResolverBuilderRuntimeContext, ServiceProviderEngineScope)
at ResolveService(ILEmitResolverBuilderRuntimeContext, 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_ContextServices()
at Microsoft.EntityFrameworkCore.DbContext.get_ChangeTracker()
at Volo.Abp.EntityFrameworkCore.AbpDbContext`1.Initialize(AbpEfCoreDbContextInitializationContext initializationContext)
at Volo.Abp.Uow.EntityFrameworkCore.UnitOfWorkDbContextProvider`1.CreateDbContextAsync(IUnitOfWork unitOfWork, String connectionStringName, String connectionString)
at Volo.Abp.Uow.EntityFrameworkCore.UnitOfWorkDbContextProvider`1.GetDbContextAsync()
at Volo.Abp.Domain.Repositories.EntityFrameworkCore.EfCoreRepository`2.GetDbSetAsync()
at Volo.Abp.Domain.Repositories.EntityFrameworkCore.EfCoreRepository`2.GetQueryableAsync()
at Shared.UserNotifications.EfCoreUserNotificationRepository.GetCountAsync(Specification`1 spec, CancellationToken cancellationToken) in C:\Shepherdv2.0\Shepherd2\modules\Shared\src\Shared.EntityFrameworkCore\UserNotifications\EfCoreUserNotificationRepository.cs:line 36
at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo)
at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue`1.ProceedAsync()
at Volo.Abp.Uow.UnitOfWorkInterceptor.InterceptAsync(IAbpMethodInvocation invocation)
at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter`1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func`3 proceed)
at Shared.UserNotifications.UserNotificationsAppService.GetListAsync(GetUserNotificationsInput input, CancellationToken cancellationToken) in C:\Shepherdv2.0\Shepherd2\modules\Shared\src\Shared.Application\UserNotifications\UserNotificationsAppService.cs:line 36
at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo)
at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue`1.ProceedAsync()
at Volo.Abp.Auditing.AuditingInterceptor.InterceptAsync(IAbpMethodInvocation invocation)
at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter`1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func`3 proceed)
at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo)
at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue`1.ProceedAsync()
at Volo.Abp.Authorization.AuthorizationInterceptor.InterceptAsync(IAbpMethodInvocation invocation)
at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter`1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func`3 proceed)
at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo)
at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue`1.ProceedAsync()
at Volo.Abp.GlobalFeatures.GlobalFeatureInterceptor.InterceptAsync(IAbpMethodInvocation invocation)
at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter`1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func`3 proceed)
at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo)
at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue`1.ProceedAsync()
at Volo.Abp.Validation.ValidationInterceptor.InterceptAsync(IAbpMethodInvocation invocation)
at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter`1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func`3 proceed)
at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo)
at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue`1.ProceedAsync()
at Volo.Abp.Uow.UnitOfWorkInterceptor.InterceptAsync(IAbpMethodInvocation invocation)
at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter`1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func`3 proceed)
at lambda_method5998(Closure, Object)
at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.AwaitableObjectResultExecutor.Execute(ActionContext actionContext, IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask`1 actionResultValueTask)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextExceptionFilterAsync>g__Awaited|26_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
- Steps to reproduce the issue:
- We created a modular monolith where we have a Shared Module that includes four domains (for notification) added as
DbSets to SharedDbContext and ISharedDbContext, as seen below:
public class Notification : Entity<int>
{
public Notification() { }
public Notification(int notificationTemplateId, string? dataValue, ICollection<UserNotification> userNotifications)
{
NotificationTemplateId = notificationTemplateId;
DataValue = dataValue;
UserNotifications = userNotifications;
}
[ForeignKey(nameof(Template))]
public virtual int NotificationTemplateId { get; set; }
[CanBeNull]
public virtual string? DataValue { get; set; }
public NotificationTemplate Template { get; set; }
public ICollection<UserNotification> UserNotifications { get; set; }
}
public class NotificationTemplate : AggregateRoot<int>
{
public NotificationTemplate(string resourceName, string urlPath, NotificationCode code)
{
Check.NotNull(resourceName, nameof(resourceName));
Check.NotNull(code, nameof(code));
ResourceName = resourceName;
UrlPath = urlPath;
Code = code;
}
[NotNull]
public virtual string ResourceName { get; set; }
[CanBeNull]
public virtual string UrlPath { get; set; }
public virtual NotificationCode Code { get; set; }
public ICollection<Notification> Notifications { get; set; }
}
public class UserDevice : CreationAuditedAggregateRootWithUser<int, IdentityUser>
{
public virtual Guid UserId { get; set; }
public virtual string DeviceId { get; set; }
public UserDevice() { }
public UserDevice(Guid userId, string deviceId)
{
Check.NotNull(userId, nameof(userId));
Check.NotNull(deviceId, nameof(deviceId));
Check.Length(deviceId, nameof(deviceId), UserDeviceConsts.DeviceIdMaxLength, UserDeviceConsts.DeviceIdMinLength);
UserId = userId;
DeviceId = deviceId;
}
}
public class UserNotification : FullAuditedEntityWithUser<int, IdentityUser>
{
public UserNotification() { }
public UserNotification(Guid userId, int? notificationId = null, bool isRead = false)
{
Check.NotNull(userId, nameof(userId));
NotificationId = notificationId;
UserId = userId;
IsRead = isRead;
}
[ForeignKey(nameof(User))]
public virtual Guid UserId { get; set; }
[ForeignKey(nameof(Notification))]
public virtual int? NotificationId { get; set; }
public virtual bool IsRead { get; set; }
public IdentityUser User { get; set; }
public Notification Notification { get; set; }
public void SetAsRead() => IsRead = true;
}
- The configuration for the domains:
public static void ConfigureNotifications(this ModelBuilder builder)
{
if (builder.IsHostDatabase())
{
builder.Entity<Notification>(b =>
{
b.ToTable(SharedDbProperties.DbTablePrefix + "Notifications", SharedDbProperties.DbSchema);
b.ConfigureByConvention();
b.Property(x => x.NotificationTemplateId).HasColumnName(nameof(Notification.NotificationTemplateId));
b.Property(x => x.DataValue).HasColumnName(nameof(Notification.DataValue));
});
}
}
public static void ConfigureNotificationTemplates(this ModelBuilder builder)
{
if (builder.IsHostDatabase())
{
builder.Entity<NotificationTemplate>(b =>
{
b.ToTable(SharedDbProperties.DbTablePrefix + "NotificationTemplates", SharedDbProperties.DbSchema);
b.ConfigureByConvention();
b.Property(x => x.ResourceName).HasColumnName(nameof(NotificationTemplate.ResourceName)).IsRequired();
b.Property(x => x.UrlPath).HasColumnName(nameof(NotificationTemplate.UrlPath));
});
}
}
public static void ConfigureUserDevices(this ModelBuilder builder)
{
if (builder.IsHostDatabase())
{
builder.Entity<UserDevice>(b =>
{
b.ToTable(SharedDbProperties.DbTablePrefix + "UserDevices", SharedDbProperties.DbSchema);
b.ConfigureByConvention();
b.Property(x => x.UserId).HasColumnName(nameof(UserDevice.UserId));
b.Property(x => x.DeviceId).HasColumnName(nameof(UserDevice.DeviceId)).IsRequired().HasMaxLength(UserDeviceConsts.DeviceIdMaxLength);
});
}
}
public static void ConfigureUserNotifications(this ModelBuilder builder)
{
if (builder.IsHostDatabase())
{
builder.Entity<UserNotification>(b =>
{
b.ToTable(SharedDbProperties.DbTablePrefix + "UserNotifications", SharedDbProperties.DbSchema);
b.ConfigureByConvention();
b.Property(x => x.UserId).HasColumnName(nameof(UserNotification.UserId));
b.Property(x => x.NotificationId).HasColumnName(nameof(UserNotification.NotificationId));
b.Property(x => x.IsRead).HasColumnName(nameof(UserNotification.IsRead));
b.HasOne(x => x.Notification).WithMany(x => x.UserNotifications).HasForeignKey(x => x.NotificationId);
});
}
}
- We have a SeedContributor for NotificationTemplate:
public class NotificationTemplateDataSeedContributor : IDataSeedContributor, ITransientDependency
{
private readonly INotificationTemplateRepository _notificationTemplateRepository;
private readonly IUnitOfWorkManager _unitOfWorkManager;
public NotificationTemplateDataSeedContributor(
INotificationTemplateRepository notificationTemplateRepository,
IUnitOfWorkManager unitOfWorkManager)
{
_notificationTemplateRepository = notificationTemplateRepository;
_unitOfWorkManager = unitOfWorkManager;
}
public async Task SeedAsync(DataSeedContext context)
{
IEnumerable<NotificationTemplate> notificationTemplates = await _notificationTemplateRepository.GetListAsync();
NotificationCode[] notificationCodes = Enum.GetValues<NotificationCode>();
foreach (var notificationCode in notificationCodes)
await InsertIfNotExistAsync(notificationTemplates, notificationCode);
}
private async Task InsertIfNotExistAsync(IEnumerable<NotificationTemplate> notificationTemplates, NotificationCode notificationCode)
{
using IUnitOfWork uow = _unitOfWorkManager.Begin(requiresNew: true, isTransactional: true);
bool isExist = notificationTemplates.Any(x => x.Code == notificationCode);
if (!isExist)
{
NotificationTemplate notificationTemplate = new(notificationCode.ToString(), string.Empty, notificationCode);
await _notificationTemplateRepository.InsertAsync(notificationTemplate);
}
await uow.CompleteAsync();
}
}
*When we run the DbMigrator we got this exception:
