最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

entity framework - The foreign key property 'UserRole.UserId1' was created in shadow state - Stack Overflow

programmeradmin1浏览0评论

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?

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?

Share Improve this question edited Feb 16 at 9:42 hrdfgn asked Feb 16 at 9:40 hrdfgnhrdfgn 53 bronze badges
Add a comment  | 

2 Answers 2

Reset to default 0

The mapping doesn't appear to have any obvious issues, but the null-able properties and FKs are likely an issue. Remove the null-ability on the UserRole:

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; }
}

I would also recommend removing the null-ability on the UserRoles collection as well and remove the setter access coupled with an initialization:

public virtual ICollection<UserRole> UserRoles { get; } = [];

It can be tempting to avoid C# 8's compiler warning about null reference types by marking everything as null-able to keep it happy, but this can end up making properties intended for FKs unsuitable for the relationship they intend to represent. Instead you can look at using a null fiveness default: `=null!" or my preferred approach using a marked default constructor:

#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
        /// <summary>
        /// Constructor used by EF.
        /// </summary>
        protected UserRole() 
        { }
#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.

You can use a public default constructor or create a suitable parameterized public constructor to ensure the entities are constructed in a valid state.

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());
    }
发布评论

评论列表(0)

  1. 暂无评论