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 badges2 Answers
Reset to default 0The 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());
}