实体框架:无法在“xxx”类上配置,因为它是派生类型

Trí*_*hồn 3 entity-framework asp.net-core

当我尝试自己添加“AppUserRoles”表以从 User 访问 UserRoles 时,出现此错误,例如:

from u in _userManager.Users.Where(x => x.UserRoles "contain" "some codition here")
Run Code Online (Sandbox Code Playgroud)

我得到了这个错误:

无法在“AppUserRoles”上配置密钥,因为它是派生类型。必须在根类型“IdentityUserRole”上配置密钥。如果您不打算将“IdentityUserRole”包含在模型中,请确保它不包含在上下文的 DbSet 属性中、在对 ModelBuilder 的配置调用中引用、或从包含的类型的导航属性中引用在模型中。

这是我之前的代码,运行正常:

builder.Entity<IdentityUserRole<Guid>>().ToTable("AppUserRoles")
.HasKey(x => new { x.RoleId, x.UserId });
Run Code Online (Sandbox Code Playgroud)

--->我改成这样:

我的用户等级

[Table("AppUsers")]
public class AppUser : IdentityUser<Guid>, IDateTracking, ISwitchable
{
    public virtual ICollection<AppUserRoles> UserRoles { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

我的角色课

[Table("AppRoles")]
public class AppRole : IdentityRole<Guid>
{
    public virtual ICollection<AppUserRoles> UserRoles { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

我的 appUserRole 类:

[Table("AppUserRoles")]
public class AppUserRoles : IdentityUserRole<Guid>
{

    public virtual AppUser User { get; set; }
    public virtual AppRole Role { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

我的 DbContextClass

public class AppDbContext : IdentityDbContext<AppUser, AppRole, Guid>
{
    public AppDbContext(DbContextOptions options) : base(options)
    {
    }
    public DbSet<AppUser> AppUsers { get; set; }
    public DbSet<AppRole> AppRoles { get; set; }
    public DbSet<AppUserRoles> AppUserRoles { get; set; }

    protected override void OnModelCreating(ModelBuilder builder)
    {
        #region Identity Config

        builder.Entity<IdentityUserClaim<Guid>>().ToTable("AppUserClaims").HasKey(x => x.Id);

        builder.Entity<IdentityUserLogin<Guid>>().ToTable("AppUserLogins").HasKey(x => x.UserId);

        builder.Entity<AppUserRoles>(userRole =>
        {
            userRole.HasKey(ur => new { ur.UserId, ur.RoleId });

            userRole.HasOne(ur => ur.Role)
                .WithMany(r => r.UserRoles)
                .HasForeignKey(ur => ur.RoleId)
                .IsRequired();

            userRole.HasOne(ur => ur.User)
                .WithMany(r => r.UserRoles)
                .HasForeignKey(ur => ur.UserId)
                .IsRequired();
        });

        builder.Entity<IdentityUserToken<Guid>>().ToTable("AppUserTokens")
           .HasKey(x => new { x.UserId });

        #endregion Identity Config

    }

    public override int SaveChanges()
    {
        var modified = ChangeTracker.Entries().Where(e => e.State == EntityState.Modified || e.State == EntityState.Added);

        foreach (EntityEntry item in modified)
        {
            var changedOrAddedItem = item.Entity as IDateTracking;
            if (changedOrAddedItem != null)
            {
                if (item.State == EntityState.Added)
                {
                    changedOrAddedItem.DateCreated = DateTime.Now;
                }
                changedOrAddedItem.DateModified = DateTime.Now;
            }
        }
        return base.SaveChanges();
    }
}

public class DesignTimeDbContextFactory : IDesignTimeDbContextFactory<AppDbContext>
{
    public AppDbContext CreateDbContext(string[] args)
    {
        IConfiguration configuration = new ConfigurationBuilder()
            .SetBasePath(Directory.GetCurrentDirectory())
            .AddJsonFile("appsettings.json").Build();
        var builder = new DbContextOptionsBuilder<AppDbContext>();
        var connectionString = configuration.GetConnectionString("DefaultConnection");
        builder.UseSqlServer(connectionString);
        return new AppDbContext(builder.Options);
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我的启动文件:

services.AddDbContext<AppDbContext>(options =>

options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"),
            o => o.MigrationsAssembly("YayoiApp.Data.EF")), 
            ServiceLifetime.Scoped);
Run Code Online (Sandbox Code Playgroud)

请给我一些建议,我已经研究了很多,但没有找到解决方案。谢谢。

Tao*_*hou 5

对于自定义IdentityUserRole<Guid>,您需要更改您的DbContext喜好

public class ApplicationDbContext : IdentityDbContext<AppUser
    , AppRole
    , Guid
    , IdentityUserClaim<Guid>
    , AppUserRoles
    , IdentityUserLogin<Guid>
    , IdentityRoleClaim<Guid>
    , IdentityUserToken<Guid>>
{
Run Code Online (Sandbox Code Playgroud)

然后将其注册到Startup.cs

services.AddIdentity<AppUser, AppRole>()
    .AddDefaultUI(UIFramework.Bootstrap4)
    .AddEntityFrameworkStores<ApplicationDbContext>();
Run Code Online (Sandbox Code Playgroud)

用例:

public class HomeController : Controller
{
    private readonly UserManager<AppUser> _userManager;
    private readonly RoleManager<AppRole> _roleManager;
    public HomeController(UserManager<AppUser> userManager
        , RoleManager<AppRole> roleManager)
    {
        _userManager = userManager;
        _roleManager = roleManager;
    }
    public async Task<IActionResult> Index()
    {
        var userName = "Tom";
        var passWord = "1qaz@WSX";
        var appUser = new AppUser
        {
            UserName = userName
        };
        await _userManager.CreateAsync(appUser, passWord);
        var roleName = "Admin";
        await _roleManager.CreateAsync(new AppRole { Name = roleName });
        await _userManager.AddToRoleAsync(appUser, roleName);
        var roles = appUser.UserRoles;
        return View();
    }
Run Code Online (Sandbox Code Playgroud)