ASP Net Core:添加与 IdentityUser 的多对多关系

Tom*_*Tom 3 .net c# asp.net asp.net-mvc asp.net-core

我需要在asp net core中添加与UserIdentity的多对多关系(即:一个用户可以有很多本书,一本书可以有很多用户所有者)

我有书课:

public class Book
{
    public int Id { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

我扩展了 UserIdentity 类:

public class ApplicationUser : IdentityUser
{
    public ICollection<UserBook> UserBooks { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

我已经创建了连接表,但我不知道如何引用身份用户 ID

public class UserBook
{
    public int UserId { get; set; }
    public ApplicationUser ApplicationUser { get; set; }
    public int BookId { get; set; }
    public Book Book { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

如何在 identityuser 表和另一个表之间正确创建多对多关系?

谢谢

Tan*_*jel 5

在您的UserBook模型类中,您使用UserId了 type intforApplicationUser但在您的ApplicationUser模型类中,您继承了默认情况下IdentityUser主键Id为 typestring的位置,这意味着您的ApplicationUser'sId为 type string。于是就有了主键类型不匹配ForeignkeyUserBook表。

解决方案1:如果保留typeApplicationUser的主键没有问题,那么只需将模型类中的类型更改为字符串,如下所示:IdstringUserIdUserBook

public class UserBook
{
    public string UserId { get; set; }
    public ApplicationUser ApplicationUser { get; set; }
    public int BookId { get; set; }
    public Book Book { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

解决方案 2:如果要将ApplicationUser的主键Id从默认 string类型更改为int,则int在继承时指定键类型IdentityUser,如下所示:

public class ApplicationUser : IdentityUser<int>
{
   public ICollection<UserBook> UserBooks { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

现在您必须对ConfigureServicesStartup 类的方法进行如下更改:

services.AddDefaultIdentity<IdentityUser<int>>() // here replace `IdentityUser` with `IdentityUser<int>`
        .AddDefaultUI()
        .AddEntityFrameworkStores<ApplicationDbContext>()
        .AddDefaultTokenProviders();
Run Code Online (Sandbox Code Playgroud)

现在最终您的模型配置(对于解决方案 1 和解决方案 2)使用 Fluent Api应如下所示:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<UserBook>()
        .HasKey(ub => new { ub.UserId, ub.BookId });

    modelBuilder.Entity<UserBook>()
        .HasOne(ub => ub.ApplicationUser)
        .WithMany(au => au.UserBooks)
        .HasForeignKey(ub => ub.UserId);

    modelBuilder.Entity<UserBook>()
        .HasOne(ub => ub.Book)
        .WithMany() // If you add `public ICollection<UserBook> UserBooks { get; set; }` navigation property to Book model class then replace `.WithMany()` with `.WithMany(b => b.UserBooks)`
        .HasForeignKey(ub => ub.BookId);
}
Run Code Online (Sandbox Code Playgroud)