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

时间:2019-02-16 00:56:51

标签: entity-framework asp.net-core

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

from u in _userManager.Users.Where(x => x.UserRoles "contain" "some codition here")

我得到了这个错误:

  

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

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

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

--->我改为:

我的用户类别

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

我的角色课

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

我的appUserRole类:

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

    public virtual AppUser User { get; set; }
    public virtual AppRole Role { get; set; }
}

我的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);
    }
}

这是我的启动文件:

services.AddDbContext<AppDbContext>(options =>

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

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

1 个答案:

答案 0 :(得分:2)

对于自定义IdentityUserRole<Guid>,您需要像

那样更改DbContext
public class ApplicationDbContext : IdentityDbContext<AppUser
    , AppRole
    , Guid
    , IdentityUserClaim<Guid>
    , AppUserRoles
    , IdentityUserLogin<Guid>
    , IdentityRoleClaim<Guid>
    , IdentityUserToken<Guid>>
{

然后将其注册到Startup.cs

services.AddIdentity<AppUser, AppRole>()
    .AddDefaultUI(UIFramework.Bootstrap4)
    .AddEntityFrameworkStores<ApplicationDbContext>();

UseCase:

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