EF Core 8 数据库首先包含身份用户表

问题描述 投票:0回答:1

我已经有一个包含身份用户表的数据库(AspNetUser,AspRole,...)。我首先使用数据库来生成模型,我已经在

program.cs
中配置了所有必要的服务。该项目运行良好,直到我开始使用与身份相关的服务(例如:
UserManager<AppUser>
)。它导致了很多异常(不可数)。我问了人工智能并用谷歌搜索了很多,但似乎希望已经破灭了。

这是生成的所有模型: 实体模型

Program.cs
配置: 配置

以下是一些例外情况,我发现了一篇具有相同问题但对我不起作用的帖子:在此处查看详细信息

  1. 不能将表“appuserroles”用于实体类型“appuserrole”,因为它用于实体类型“appuserrole(字典)”以及可能的其他实体类型,但不存在链接关系。将外键添加到主键属性上的“appuserrole”,并指向映射到“appuserroles”的另一个实体类型上的主键。

  2. Npgsql.PostgresException(0x80004005):42P01:关系“AppUser”不存在。

  3. System.InvalidOperationException:无法将表“AppRoleClaims”用于实体类型“IdentityRoleClaim”,因为它用于实体类型“AppRoleClaim”和可能的其他实体类型,但没有链接关系。将外键添加到主键属性上的“IdentityRoleClaim”,并指向映射到“AppRoleClaims”的另一个实体类型上的主键。

这是我的数据库上下文:

public partial class MyUserContext : IdentityDbContext<AspNetUser, IdentityRole<Guid>, Guid>
{
    public MyUserContext()
    {
    }

    public MyUserContext(DbContextOptions<MyUserContext> options)
        : base(options)
    {
    }

    public virtual DbSet<AspNetRole> AspNetRoles { get; set; }
    public virtual DbSet<AspNetRoleClaim> AspNetRoleClaims { get; set; }
    public virtual DbSet<AspNetUser> AspNetUsers { get; set; }
    public virtual DbSet<AspNetUserClaim> AspNetUserClaims { get; set; }
    public virtual DbSet<AspNetUserLogin> AspNetUserLogins { get; set; }
    public virtual DbSet<AspNetUserToken> AspNetUserTokens { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        => optionsBuilder.UseSqlServer("server=(local);database=MyUser;Trusted_Connection=True;TrustServerCertificate=True;uid=sa;pwd=T@n12345678901;");

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<AspNetRole>(entity =>
        {
            entity.HasIndex(e => e.NormalizedName, "RoleNameIndex")
                .IsUnique()
                .HasFilter("([NormalizedName] IS NOT NULL)");

            entity.Property(e => e.Id).ValueGeneratedNever();
            entity.Property(e => e.Name).HasMaxLength(256);
            entity.Property(e => e.NormalizedName).HasMaxLength(256);
        });

        modelBuilder.Entity<AspNetRoleClaim>(entity =>
        {
            entity.HasIndex(e => e.RoleId, "IX_AspNetRoleClaims_RoleId");
            entity.HasOne(d => d.Role).WithMany(p => p.AspNetRoleClaims).HasForeignKey(d => d.RoleId);
        });

        modelBuilder.Entity<AspNetUser>(entity =>
        {
            entity.HasIndex(e => e.NormalizedEmail, "EmailIndex");
            entity.HasIndex(e => e.NormalizedUserName, "UserNameIndex")
                .IsUnique()
                .HasFilter("([NormalizedUserName] IS NOT NULL)");

            entity.Property(e => e.Id).ValueGeneratedNever();
            entity.Property(e => e.Email).HasMaxLength(256);
            entity.Property(e => e.NormalizedEmail).HasMaxLength(256);
            entity.Property(e => e.NormalizedUserName).HasMaxLength(256);
            entity.Property(e => e.UserName).HasMaxLength(256);

            entity.HasMany(d => d.Roles).WithMany(p => p.Users)
                .UsingEntity<Dictionary<string, object>>(
                    "AspNetUserRole",
                    r => r.HasOne<AspNetRole>().WithMany().HasForeignKey("RoleId"),
                    l => l.HasOne<AspNetUser>().WithMany().HasForeignKey("UserId"),
                    j =>
                    {
                        j.HasKey("UserId", "RoleId");
                        j.ToTable("AspNetUserRoles");
                        j.HasIndex(new[] { "RoleId" }, "IX_AspNetUserRoles_RoleId");
                    });
        });

        modelBuilder.Entity<AspNetUserClaim>(entity =>
        {
            entity.HasIndex(e => e.UserId, "IX_AspNetUserClaims_UserId");
            entity.HasOne(d => d.User).WithMany(p => p.AspNetUserClaims).HasForeignKey(d => d.UserId);
        });

        modelBuilder.Entity<AspNetUserLogin>(entity =>
        {
            entity.HasKey(e => new { e.LoginProvider, e.ProviderKey });
            entity.HasIndex(e => e.UserId, "IX_AspNetUserLogins_UserId");
            entity.HasOne(d => d.User).WithMany(p => p.AspNetUserLogins).HasForeignKey(d => d.UserId);
        });

        modelBuilder.Entity<AspNetUserToken>(entity =>
        {
            entity.HasKey(e => new { e.UserId, e.LoginProvider, e.Name });
            entity.HasOne(d => d.User).WithMany(p => p.AspNetUserTokens).HasForeignKey(d => d.UserId);
        });

        OnModelCreatingPartial(modelBuilder);
    }

    partial void OnModelCreatingPartial(ModelBuilder modelBuilder);
}
.net entity-framework-core asp.net-identity ef-database-first
1个回答
0
投票

如果您的代码基于示例,则它们不会为 AspNetUserRole 等表使用显式实体,因此您不应尝试声明一个实体。这些表是用于多对多关系的连接表,并且在许多情况下是可选的。

要解决您的问题,请删除这些加入实体(例如 AspNetUserRole)的实体声明。您的映射已经适合连接表。

例如您的代码:

entity.HasMany(d => d.Roles).WithMany(p => p.Users)
            .UsingEntity<Dictionary<string, object>>(
                "AspNetUserRole",
                r => r.HasOne<AspNetRole>().WithMany().HasForeignKey("RoleId"),
                l => l.HasOne<AspNetUser>().WithMany().HasForeignKey("UserId"),
                j =>
                {
                    j.HasKey("UserId", "RoleId");
                    j.ToTable("AspNetUserRoles");
                    j.HasIndex(new[] { "RoleId" }, "IX_AspNetUserRoles_RoleId");
                });

这是将 User 和 Role 之间的关系声明到 AspNetUserRoles 表,但将其映射为基本字典而不是显式实体类。不需要显式类,但您可以调整映射以使用它。在任何一种情况下,您都不需要为多对多连接表声明 DbSet,只需让 EF 找出您的实体应分别使用 User.Roles 和 Role.Users 的位置即可。

© www.soinside.com 2019 - 2024. All rights reserved.