Learn More, Pay Less!
Limited Time Offer!
Open Closed

The entity type 'IdentityUserLogin' requires a primary key to be defined. If you intended to use a keyless entity type, call 'HasNoKey' in 'OnModelCreating'. #8716


User avatar
0
idreesh created
  • 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:


13 Answer(s)
  • User Avatar
    0
    Anjali_Musmade created
    Support Team Support Team Member

    Hello

    I think this is same with https://abp.io/support/questions/1271/Add-relation-between-AbpUser-to-My-Table#answer-0ef35452-cfbd-16ad-44c0-39fc57ccd99e

    Can you check?

    Thank you.

  • User Avatar
    0
    idreesh created

    Hello Anjali,

    Thank you for the prompt response.

    It seems like we already have it:

    Any other reason why it would not work?

  • User Avatar
    0
    Anjali_Musmade created
    Support Team Support Team Member

    Hello

    a composite key using LoginProvider and ProviderKey, which are meant to be the primary keys for IdentityUserLogin:

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
        modelBuilder.Entity<IdentityUserLogin>(b =>
        {
            b.HasKey(l => new { l.LoginProvider, l.ProviderKey });
        });
    }
    

    Try to this code and check it's work or not ?

    Thank you.

  • User Avatar
    0
    idreesh created

    We tried it and the exception remains. What else could be the source of the problem?

  • User Avatar
    0
    Anjali_Musmade created
    Support Team Support Team Member

    please check once this link https://github.com/abpframework/abp/issues/8019#issuecomment-796776155

  • User Avatar
    0
    idreesh created

    We've tried it and it did not work. I noticed that our solution does not attempt to modify the TenantConnectionString, nor do we have the method builder.ConfigureSaas(); So, maybe this is not related to our solution.

    If you need more investigation, we can share the code with you. How do you feel about sharing the code? And how would you rather us share the code with you?

  • User Avatar
    0
    Anjali_Musmade created
    Support Team Support Team Member

    Hello ,

    Please share your project support@abp.io email along with ticket no.

    Thanks,

  • User Avatar
    0
    idreesh created

    Hello ,

    Please share your project support@abp.io email along with ticket no.

    Thanks,

    I already shared the solution with you and mention the ticket number in the share message, below is the link for easy access

    https://drive.google.com/file/d/1VA603vKxEUhktFXnMh58phJ0PhoZ_UNN/view?usp=sharing

    if you want to see the error only run the migrator project and you will see the error in the seed contributor file of the shared project in module folder

  • User Avatar
    0
    idreesh created

    Any Updates?

  • User Avatar
    0
    EngincanV created
    Support Team .NET Developer

    Hi, I got your project now and trying to reproduce the problem. I will write back to you asap.

    Regards.

  • User Avatar
    0
    EngincanV created
    Support Team .NET Developer

    Hi, I checked your project and found the problem. In your shared.entityframeworkcore project, you should call the builder.ConfigureIdentityPro() before your entity configuration. Because you are using the FullAuditedEntityWithUser in the UserNotification entity.

    Here is what you should do:

    1. Add <PackageReference Include="Volo.Abp.Identity.Pro.EntityFrameworkCore" Version="9.0.4" /> to Shared.EntityFrameworkCore.csproj.
    2. Add typeof(AbpIdentityProEntityFrameworkCoreModule) this depends on statement to SharedEntityFrameworkCoreModule class.
    3. Open the SharedDbContext class, and update it as follows (don't forget to add builder.ConfigureIdentityPro()):
    using Microsoft.EntityFrameworkCore;
    using Shared.EntityFrameworkCore.Configurations;
    using Shared.Notifications;
    using Shared.NotificationTemplates;
    using Shared.UserDevices;
    using Shared.UserNotifications;
    using Volo.Abp.Data;
    using Volo.Abp.DependencyInjection;
    using Volo.Abp.EntityFrameworkCore;
    using Volo.Abp.Identity;
    using Volo.Abp.Identity.EntityFrameworkCore;
    
    namespace Shared.EntityFrameworkCore;
    
    [ReplaceDbContext(typeof(IIdentityProDbContext))]
    [ConnectionStringName(SharedDbProperties.ConnectionStringName)]
    public class SharedDbContext : AbpDbContext<SharedDbContext>, ISharedDbContext, IIdentityProDbContext
    {
        /* Add DbSet for each Aggregate Root here. Example:
         * public DbSet<Question> Questions { get; set; }
         */
    
        public DbSet<UserNotification> UserNotifications { get; set; }
        public DbSet<Notification> Notifications { get; set; }
        public DbSet<NotificationTemplate> NotificationTemplates { get; set; }
        public DbSet<UserDevice> UserDevices { get; set; }
    
        public SharedDbContext(DbContextOptions<SharedDbContext> options)
            : base(options)
        {
    
        }
    
        protected override void OnModelCreating(ModelBuilder builder)
        {
            base.OnModelCreating(builder);
    
            builder.ConfigureIdentityPro();
            builder.ConfigureShared();
    
        }
    
        //Identity
        public DbSet<IdentityUser> Users { get; }
        public DbSet<IdentityRole> Roles { get; }
        public DbSet<IdentityClaimType> ClaimTypes { get; }
        public DbSet<OrganizationUnit> OrganizationUnits { get; }
        public DbSet<IdentitySecurityLog> SecurityLogs { get; }
        public DbSet<IdentityLinkUser> LinkUsers { get; }
        public DbSet<IdentityUserDelegation> UserDelegations { get; }
        public DbSet<IdentitySession> Sessions { get; }
    }
    

    Then, run the dbmigrator without having a problem.

  • User Avatar
    0
    idreesh created

    Thanks, the issue is resolved. So, for each module, if I want to use FullAuditedEntityWithUser or establish a relationship with IdentityUser, I need to follow the same steps, correct?

  • User Avatar
    0
    EngincanV created
    Support Team .NET Developer

    Thanks, the issue is resolved. So, for each module, if I want to use FullAuditedEntityWithUser or establish a relationship with IdentityUser, I need to follow the same steps, correct?

    Yes, that's right 👍Because, you need to have the relationship for the IdentityUser entity.

    I'm closing the question since your problem is resolved. Best regards.

Made with ❤️ on ABP v9.2.0-preview. Updated on February 13, 2025, 10:35