【问题标题】:Entity Framework: Cannot be configured on 'xxx' class because it is a derived type实体框架:无法在“xxx”类上配置,因为它是派生类型
【发布时间】:2019-02-19 16:15:38
【问题描述】:

我尝试自己添加“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);

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

【问题讨论】:

  • 为什么要修改identityuserrole的名字?

标签: entity-framework asp.net-core


【解决方案1】:

对于自定义IdentityUserRole&lt;Guid&gt;,您需要更改您的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>();

用例:

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

【讨论】:

  • 就我而言,我还需要添加 Microsoft.EntityFrameworkCore.Proxies 包来获得结果。 services.AddDbContext(options => options.UseLazyLoadingProxies() .UseSqlServer(Configuration.GetConnectionString("DefaultConnection"), o => o.MigrationsAssembly("YayoiApp.Data.EF")), ServiceLifetime.Scoped);
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多