entity-frameworkentity-framework-coreasp.net-identityentity-framework-migrations

The foreign key property 'UserRole.UserId1' was created in shadow state


EF creates UserId1 and RoleId1 in UserRoles table when I try to add migration. there are messages:

The foreign key property 'UserRole.RoleId1' was created in shadow state because a conflicting property with the simple name 'RoleId' exists in the entity type, but is either not mapped, is already used for another relationship, or is incompatible with the associated primary key type.

The foreign key property 'UserRole.UserId1' was created in shadow state because a conflicting property with the simple name 'UserId' exists in the entity type, but is either not mapped, is already used for another relationship, or is incompatible with the associated primary key type.

my models:

public interface IEntity
{
    public Guid Id { get; set; }
}

public interface IBaseEntity : IEntity
{
    public DateTime CreatedAt { get; set; }
    public DateTime? UpdatedAt { get; set; }
    public DateTime? DeletedAt { get; set; }
    public bool IsDeleted { get; set; }
}

public class User : IdentityUser<Guid>, IBaseEntity
{
    public string? FirstName { get; set; }
    public string? LastName { get; set; }
    public DateTime DateOfBirth { get; set; }

    public DateTime CreatedAt { get; set; }
    public DateTime? UpdatedAt { get; set; }
    public DateTime? DeletedAt { get; set; }
    public bool IsDeleted { get; set; }
    public bool IsBlocked { get; set; }


    public virtual ICollection<UserRole>? UserRoles { get; set; }
}

public class Role : IdentityRole<Guid>, IBaseEntity
{
    public string? Description { get; set; }
    public DateTime CreatedAt { get; set; }
    public DateTime? UpdatedAt { get; set; }
    public DateTime? DeletedAt { get; set; }
    public bool IsDeleted { get; set; }

    public virtual ICollection<UserRole>? UserRoles { get; set; }
}

public class UserRole : IdentityUserRole<Guid>
{
    public Guid? UserId { get; set; }
    public Guid? RoleId { get; set; }

    public virtual User? User { get; set; }
    public virtual Role? Role { get; set; }
}

and my configs are

    public class RoleConfiguration : IEntityTypeConfiguration<Role>
{
    public void Configure(EntityTypeBuilder<Role> builder)
    {
        builder
            .ToTable("Roles");

        builder
            .HasKey(r => r.Id);

        builder
            .HasMany(x => x.UserRoles)
            .WithOne(x => x.Role)
            .HasForeignKey(x => x.RoleId)
            .IsRequired();
    }
}

public class UserConfiguration : IEntityTypeConfiguration<User>
{
    public void Configure(EntityTypeBuilder<User> builder)
    {
        builder
            .ToTable("Users");

        builder
            .Property(user => user.FirstName)
            .HasMaxLength(UserConstants.FirstNameMaxLength);

        builder
            .Property(user => user.LastName)
            .HasMaxLength(UserConstants.LastNameMaxLength);

        builder
            .Property(user => user.Email)
            .HasMaxLength(UserConstants.EmailMaxLength);

        builder
            .Property(user => user.PhoneNumber)
            .HasMaxLength(UserConstants.PhoneMaxLength);

        builder
            .HasMany(x => x.UserRoles)
            .WithOne(x => x.User)
            .HasForeignKey(x => x.UserId)
            .IsRequired();

        builder
            .Metadata
            .RemoveIndex(new[] { builder.Property(x => x.NormalizedUserName).Metadata});

        builder
            .HasIndex(x => new { x.NormalizedUserName })
            .HasName("UserNameIndex")
            .IsUnique();
    }
}

public class UserRoleConfiguration : IEntityTypeConfiguration<UserRole>
{
    public void Configure(EntityTypeBuilder<UserRole> builder)
    {
        builder
            .ToTable("UserRoles");
    }
}

I tried to change relations in congigs, remove interface inheritance in models, remove RoleId and UserId from UserRole

What am I doing wrong?


Solution

  • After a few days I found a stupid mistake in DbContext

    it was

    public class AppIdentityDbContext : IdentityDbContext<User, Role, Guid, UserClaim, UserRole, UserLogin, RoleClaim, UserToken>, IAppIdentityDbContext
    {
        public DbSet<Client> Clients { get; set; }
        public DbSet<ClientScope> ClientScopes { get; set; }
        public DbSet<RefreshToken> RefreshTokens { get; set; }
        public DbSet<Scope> Scopes { get; set; }
    
        public AppIdentityDbContext(DbContextOptions<AppIdentityDbContext> options)
            : base(options)
        { }
    
        protected override void OnModelCreating(ModelBuilder builder)
        {
            builder.ApplyConfiguration(new ClientConfiguration());
            builder.ApplyConfiguration(new ClientScopeConfiguration());
            builder.ApplyConfiguration(new RefreshTokenConfiguration());
            builder.ApplyConfiguration(new RoleConfiguration());
            builder.ApplyConfiguration(new RoleClaimConfiguration());
            builder.ApplyConfiguration(new ScopeConfiguration());
            builder.ApplyConfiguration(new UserConfiguration());
            builder.ApplyConfiguration(new UserClaimConfiguration());
            builder.ApplyConfiguration(new UserLoginConfiguration());
            builder.ApplyConfiguration(new UserRoleConfiguration());
            builder.ApplyConfiguration(new UserTokenConfiguration());
            base.OnModelCreating(builder);
        }
    }
    

    the problem is 'base.OnModelCreating' should be BEFORE another configs like there

            protected override void OnModelCreating(ModelBuilder builder)
        {
            base.OnModelCreating(builder);
            builder.ApplyConfiguration(new ClientConfiguration());
            builder.ApplyConfiguration(new ClientScopeConfiguration());
            builder.ApplyConfiguration(new RefreshTokenConfiguration());
            builder.ApplyConfiguration(new RoleConfiguration());
            builder.ApplyConfiguration(new RoleClaimConfiguration());
            builder.ApplyConfiguration(new ScopeConfiguration());
            builder.ApplyConfiguration(new UserConfiguration());
            builder.ApplyConfiguration(new UserClaimConfiguration());
            builder.ApplyConfiguration(new UserLoginConfiguration());
            builder.ApplyConfiguration(new UserRoleConfiguration());
            builder.ApplyConfiguration(new UserTokenConfiguration());
        }