【问题标题】:ASP Net Core: add many to many relationship with IdentityUserASP Net Core:添加与 IdentityUser 的多对多关系
【发布时间】:2019-02-09 16:32:24
【问题描述】:

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

我有书课:

public class Book
{
    public int Id { get; set; }
}

我已经扩展了 UserIdentity 类:

public class ApplicationUser : IdentityUser
{
    public ICollection<UserBook> UserBooks { get; set; }
}

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

public class UserBook
{
    public int UserId { get; set; }
    public ApplicationUser ApplicationUser { get; set; }
    public int BookId { get; set; }
    public Book Book { get; set; }
}

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

谢谢

【问题讨论】:

    标签: c# asp.net .net asp.net-mvc asp.net-core


    【解决方案1】:

    在您的UserBook 模型类中,您使用int 类型的UserId 来表示ApplicationUser,但在您的ApplicationUser 模型类中,您继承了IdentityUser,其中主键Id 的类型为@987654328 @ 默认情况下,这意味着您的ApplicationUser 的Id 是string 类型。所以UserBook表中Foreignkey的主键类型会不匹配。

    Solution-1:如果你保留ApplicationUser的主键Idstring类型没有问题,那么只需将UserId类型改为@987654338中的字符串@模型类如下:

    public class UserBook
    {
        public string UserId { get; set; }
        public ApplicationUser ApplicationUser { get; set; }
        public int BookId { get; set; }
        public Book Book { get; set; }
    }
    

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

    public class ApplicationUser : IdentityUser<int>
    {
       public ICollection<UserBook> UserBooks { get; set; }
    }
    

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

    services.AddDefaultIdentity<IdentityUser<int>>() // here replace `IdentityUser` with `IdentityUser<int>`
            .AddDefaultUI()
            .AddEntityFrameworkStores<ApplicationDbContext>()
            .AddDefaultTokenProviders();
    

    现在您的模型配置(对于解决方案-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);
    }
    

    【讨论】:

    • 我已在 UserBook 模型类中将 UserId 从 int 更改为 string。无论如何,当我进行迁移时,我收到以下错误:实体类型“UserBook”需要定义主键。
    • @Tom 你可能错过了我的 Fluent Api 配置。
    【解决方案2】:

    简单,public string ApplicationUserId { get; set; }

    ApplicationUser 的默认密钥类型为string。

    如果你确实想使用 int,那么简单:

    public class ApplicationUser : IdentityUser<int>
    

    请务必在您的 DbContext 中声明此关系。

    这是一个示例:

    entityTypeBuilder.HasKey(pcp => new { pcp.CurrencyPairId, pcp.IsMain })
                    .HasName("PartialCurrencyPair_CK_CurrencyPairId_IsMain");
    
                entityTypeBuilder.HasOne(pcp => pcp.Currency).WithMany(c => c.PartialCurrencyPairs)
                    .HasForeignKey(pcp => pcp.CurrencyId)
                    .HasConstraintName("PartialCurrencyPairs_Currency_Constraint");
                entityTypeBuilder.HasOne(pcp => pcp.CurrencyPair).WithMany(cp => cp.PartialCurrencyPairs)
                    .HasForeignKey(pcp => pcp.CurrencyPairId)
                    .HasConstraintName("PartialCurrencyPairs_CurrencyPair_Constraint");
    

    编辑

    您不必将泛型与基类 (IdentityUser) 一起显式定义。您只需这样做:

    services.AddIdentity<ApplicationUser, Role>()
                    .AddEntityFrameworkStores<NozomiAuthContext>()
                    .AddDefaultTokenProviders();
    

    这假设 Role 和 ApplicationUser 共享相同的密钥类型 string,它们分别是 IdentityRole 和 IdentityUser 的重载。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-09-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-20
      • 2022-10-25
      • 1970-01-01
      相关资源
      最近更新 更多