Asp.net-Core

EF Core 2 如何在 IdentityUser 上包含角色導航屬性?

  • April 5, 2022

我正在使用 EF Core 2 設置一個新項目,並且我需要在 IdentityUser 上有一個導航屬性,因此當我查詢使用者時,我可以包含(x => x.Roles)並獲取使用者所在的角色。

Github 上的這篇文章有一些想法,但我已經嘗試了每一個和所有導致問題,通過在身份表上創建新/重複欄位或導致遷移問題。EF 團隊中的任何人都沒有發表官方評論。

https://github.com/aspnet/Identity/issues/1361

我想知道是否有人可以正常工作?並且可以分享他們的 EF DB 映射和模型。

請參閱“將身份驗證和身份遷移到 ASP.NET Core 2.0”的文件,特別是“添加 IdentityUser POCO 導航屬性”部分:

IdentityUser基本POCO(普通舊 CLR 對象)的實體框架 (EF) 核心導航屬性 已被刪除。如果您的 1.x 項目使用了這些屬性,請手動將它們添加回 2.0 項目:

/// <summary>
/// Navigation property for the roles this user belongs to.
/// </summary>
public virtual ICollection<IdentityUserRole<int>> Roles { get; } = new List<IdentityUserRole<int>>();

為了防止在執行 EF Core 遷移時出現重複的外鍵,請將以下內容添加到您的IdentityDbContext類的OnModelCreating 方法中(在base.OnModelCreating();呼叫之後):

protected override void OnModelCreating(ModelBuilder builder)
{
   base.OnModelCreating(builder);
   // Customize the ASP.NET Identity model and override the defaults if needed.
   // For example, you can rename the ASP.NET Identity table names and more.
   // Add your customizations after calling base.OnModelCreating(builder);

   builder.Entity<ApplicationUser>()
       .HasMany(e => e.Roles)
       .WithOne()
       .HasForeignKey(e => e.UserId)
       .IsRequired()
       .OnDelete(DeleteBehavior.Cascade);
}

編輯

IdentityUserRole以上將僅滿足通過連結表訪問對使用者持有的角色 ID 的任務。要通過導航屬性訪問角色實體本身,您需要添加另一個導航屬性(這次是針對從 繼承的實體IdentityUserRole)。請參閱以下步驟:

  1. 修改實體Roles上的導航屬性,IdentityUser如下所示:
public virtual ICollection<UserRole> Roles { get; set; } = new List<UserRole>();
  1. 創建UserRole上面引用的實體:
public class UserRole : IdentityUserRole<int>
{
   public virtual IdentityRole<int> Role { get; set; }
}
  1. 構造UserRole如下的映射:
builder.Entity<UserRole>()
   .HasOne(e => e.Role)
   .WithMany()
   .HasForeignKey(e => e.RoleId)
   .IsRequired()
   .OnDelete(DeleteBehavior.Cascade);
  1. 然後,您可以檢索實體(填充了導航屬性),如下所示:
User user = context.Set<User>()
   .Include(u => u.Roles)
   .ThenInclude(r => r.Role)
   .FirstOrDefault();

筆記:

  • 由於這是載入多對多關係的另一端,這可能會導致對數據庫的多次呼叫(請參閱N+1 問題)。
  • 當您創建一個繼承自IdentityUserRole您的新實體時,您需要遷移或重新創建數據庫。
  • 如果你想使用這個導航屬性,UserManager或者 RoleManager你需要 在你的啟動類中使用和的長格式重載,AddUserStore()例如AddRoleStore
services.AddIdentity<User, IdentityRole<int>>()
   .AddUserStore<UserStore<User, IdentityRole<int>, SqlContext, int, IdentityUserClaim<int>, UserRole, IdentityUserLogin<int>, IdentityUserToken<int>, IdentityRoleClaim<int>>>()
   .AddRoleStore<RoleStore<IdentityRole<int>, SqlContext, int, UserRole, IdentityRoleClaim<int>>>()
   .AddDefaultTokenProviders();

引用自:https://stackoverflow.com/questions/47767267