Efcore: RoleId1 and UserId1 props in UserRole when I customize Identity Models

Created on 29 Mar 2019  路  5Comments  路  Source: dotnet/efcore

By following the instructions of this article:

https://docs.microsoft.com/en-us/aspnet/core/security/authentication/customize-identity-model?view=aspnetcore-2.2#customize-the-model

I customized thtis three models
IdentityUsers, IdentityRole, IdentityUserRole

UserRole:
    public class AppUserRole : IdentityUserRole<string>
    {
         public AppUser User { get; set; }
         public AppRole Role { get; set; }
    }

AppUser:
    public class AppUser: IdentityUser<string>
    {
         ...
        public ICollection<AppUserRole> UserRoles { get; }
    }

AppRole:
    public class AppRole:IdentityRole<string>
    { 
        public virtual ICollection<AppUserRole> UserRoles { get; }
    }

and their configs:

AppUser :
            builder.HasMany(e => e.UserRoles)
                .WithOne(e => e.User)
                .HasForeignKey(ur => ur.UserId)
                .IsRequired();

AppRole:
      builder.HasMany(e => e.UserRoles)
                       .WithOne(x => x.Role)
                       .HasForeignKey(ur => ur.RoleId)
                       .IsRequired();

now when add migration EF generate new column UserId1 and UserRole1 in UserRole ( AspnetUserRole table)

and even revert and delete migration and query users and roles tables
still EF use UserId1 and RoleId1 in queries

my query:

_dbContext.Users
                .Include(x=>x.UserRoles)
                .First((x => x.UserName == "Username" ));

and get this sqlException:

SqlException: Invalid column name 'UserId1'.
Invalid column name 'RoleId1'.

why did this happen? and what should I do EF forget "UserId1" and "UserRole1" ?

EF Core version: "Microsoft.EntityFrameworkCore.SqlServer": "2.2.3"
Database Provider: Microsoft.EntityFrameworkCore.SqlServer
Operating system: Windows 10
IDE: Rider/VS2017

closed-question customer-reported

Most helpful comment

https://github.com/aspnet/AspNetCore/blob/7f4dd275511481feb2264ed7322c3b6f5d20d25c/src/Identity/EntityFrameworkCore/src/IdentityDbContext.cs#L123-L140

Identity already defines relationship between those entities without navigations. You are trying to configure using navigation properties. The issue happens in your code here
https://github.com/ableji/EFTest/blob/0653b40db6ebad93c163410db8b3b4427bf26f43/EFTest/AppDbContext.cs#L20-L33

You are defining relationships with navigations, then calling base method. Which will override FK property configuration which you are using, so the FK you configured will go to the relationship without navigations. Since the navigations you defined are still in model, conventions will add another relationship for that and create shadow FK properties for them. Essentially Identity overwrote configuration you did and your navigations caused extra relationships by convention. Best way to override Identity configuration is calling base.OnModelCreating() method first before writing own configuration code. When I move base call to start of the method and generate migration there are no extra columns.

All 5 comments

@ableji Please post a small runnable project/solution that reproduces what you are seeing so that we can investigate.

Assigning to @ajcvickers in case he wants to take a look a the repro. Ultimately it can go to @AndriySvyryd if it is a bug in his area.

https://github.com/aspnet/AspNetCore/blob/7f4dd275511481feb2264ed7322c3b6f5d20d25c/src/Identity/EntityFrameworkCore/src/IdentityDbContext.cs#L123-L140

Identity already defines relationship between those entities without navigations. You are trying to configure using navigation properties. The issue happens in your code here
https://github.com/ableji/EFTest/blob/0653b40db6ebad93c163410db8b3b4427bf26f43/EFTest/AppDbContext.cs#L20-L33

You are defining relationships with navigations, then calling base method. Which will override FK property configuration which you are using, so the FK you configured will go to the relationship without navigations. Since the navigations you defined are still in model, conventions will add another relationship for that and create shadow FK properties for them. Essentially Identity overwrote configuration you did and your navigations caused extra relationships by convention. Best way to override Identity configuration is calling base.OnModelCreating() method first before writing own configuration code. When I move base call to start of the method and generate migration there are no extra columns.

https://github.com/aspnet/AspNetCore/blob/7f4dd275511481feb2264ed7322c3b6f5d20d25c/src/Identity/EntityFrameworkCore/src/IdentityDbContext.cs#L123-L140

Identity already defines relationship between those entities without navigations. You are trying to configure using navigation properties. The issue happens in your code here
https://github.com/ableji/EFTest/blob/0653b40db6ebad93c163410db8b3b4427bf26f43/EFTest/AppDbContext.cs#L20-L33

You are defining relationships with navigations, then calling base method. Which will override FK property configuration which you are using, so the FK you configured will go to the relationship without navigations. Since the navigations you defined are still in model, conventions will add another relationship for that and create shadow FK properties for them. Essentially Identity overwrote configuration you did and your navigations caused extra relationships by convention. Best way to override Identity configuration is calling base.OnModelCreating() method first before writing own configuration code. When I move base call to start of the method and generate migration there are no extra columns.

base.OnModelCreating was my issue. I replaced it on top and I generated new migration so userid1 and roleid1 columns was dropped

Was this page helpful?
0 / 5 - 0 ratings