簡體   English   中英

Microsoft.AspNet.Identity.EntityFramework.IdentityUser 的外鍵?

[英]Foreign Key To Microsoft.AspNet.Identity.EntityFramework.IdentityUser?

我在 VS 2013 中,剛剛創建了一個 MVC 應用程序。

我正在創建一個對象,我打算在結果數據庫中擁有一個指向 AspNetUsers 表的外鍵。 該項目確實有一個 ApplicationUser(源自 IdentityUser),它看起來像與 AspNetUsers 表匹配的屬性列。

我們如何正確地為此聲明一個外鍵?

public MyObject
{
   public string UserId { get; set; }

   [ForeignKey("UserId")]
   public ApplicationUser User { get; set;}

   // other properties
}

現在,我修改 ApplicationUser 以獲得 MyObjects 的集合:

public ApplicationUser : IdentityUser
{
     public virtual ICollection<MyObject> MyObjects { get; set; }    
}

這似乎是EF Code First中如何進行一對多。 但是,當我更新數據庫時,我收到錯誤消息,指出身份成員(IdentityUserLogin、IdentityUserRole 等)沒有定義密鑰。 也許這些課程不打算參與 EF Code First 遷移?

我可以“返回”並通過 SQL 語句添加外鍵,但是如果我想從 Code First 再次更新,我可能會收到錯誤(數據庫當前與舊遷移不匹配或類似)。

我們如何正確使用外鍵引用這些成員資格表?

我還嘗試使用 AspNetUsers 表的匹配屬性創建一個 AspNetUser 類。 我在 Client 類上聲明了“public AspNetUser”,而不是“public ApplicationUser”。 這樣做會導致遷移失敗 - “未應用自動遷移,因為它會導致數據丟失。”

那么,該怎么辦?

ApplicationUserMyObject之間創建一對多關系並在MyObjects表中添加“UserId”外鍵很容易。 我喜歡這個解決方案的地方在於它遵循 EF 約定,並且您的模型中不需要[ForeignKey]屬性:

public class ApplicationUser : IdentityUser
{
    public virtual ICollection<MyObject> MyObjects { get; set; }
}

public class MyObject
{
    public int MyObjectId { get; set; }

    public string MyObjectName { get; set; }

    // other properties

    public virtual ApplicationUser ApplicationUser { get; set; }
}

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
    public ApplicationDbContext()
        : base("DefaultConnection", throwIfV1Schema: false)
    {
    }

    public DbSet<MyObject> MyObjects { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        modelBuilder.Entity<MyObject>()
            .HasRequired(c => c.ApplicationUser)
            .WithMany(t => t.MyObjects)
            .Map(m => m.MapKey("UserId"));
    }
}

請注意使用 Fluent API 在MyObjects表中創建“UserId”外鍵。 此解決方案在不添加 Fluent API 的情況下仍然可以工作,但是按照慣例,您的外鍵列將在MyObjects表中命名為“ApplicationUser_Id”。

我將執行以下操作:在ApplicationUser類中,添加一個ForeignKey屬性,

public ApplicationUser : IdentityUser {
    [ForeignKey("UserID")]
    public virtual ICollection<MyCustomUser> MyCustomUsers{ get; set; }    
}

在您想要跟蹤它屬於哪個用戶的模型中,

public MyObject {
    public string UserId { get; set; }

    // other properties
}

您不需要將整個ApplicationUser實例存儲在MyObject類中, UserID將自動生成。 重要的是它是string類型, ApplicationUserID也是如此!

public MyObject
{
   .. other properties

   [MaxLength(128), ForeignKey("ApplicationUser")]
   public virtual string UserId { get; set; }

   public virtual ApplicationUser ApplicationUser { get; set;}
}

ASP.NET Identity 類不使用屬性來定義關系,它們希望由 DbContext 配置關系。

與 ASP.NET Identity 一起使用的默認 DbContext IdentityDbContext<TUser>包括配置。 所以如果你讓你的 DbContext 類繼承自IdentityDbContext<ApplicationUser>你應該一切都准備好了。

更新

如果仍然出現錯誤:“未應用自動遷移,因為它會導致數據丟失。” 然后做:

get Update-Database -Force

如果您仍然收到有關 IdentityUserLogin、IdentityUserRole 等未定義鍵的錯誤消息,那么您很可能在未先調用基本方法的情況下覆蓋了OnModelCreating中的 OnModelCreating 方法。 像這樣添加對基的調用:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    base.OnModelCreating(modelbuilder);
    // your code here
}

更新結束

如果您不想從IdentityDbContext繼承,則需要為 Identity 類添加一些配置。 一種方法是覆蓋OnModelCreating 這是IdentityDbContext<ApplicationUser>配置實體框架映射的地方。 如果您將此添加到您的 DbContext 類,它應該設置您需要的映射。

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<IdentityUserLogin>().HasKey<string>(l => l.UserId);
    modelBuilder.Entity<IdentityRole>().HasKey<string>(r => r.Id);
    modelBuilder.Entity<IdentityUserRole>().HasKey(r => new { r.RoleId, r.UserId });
}

我認為你有它倒退。 也許嘗試這樣的事情:

public MyCustomUser : IUser
{
   public string Id { get; set; }

   public string FavoriteHairColor { get; set;}
}

public ApplicationUser : IdentityUser
{
     public virtual ICollection<MyCustomUser> MyCustomUsers{ get; set; }    
}

我從這里開始記憶,所以我可能有點不對勁。 無論如何,重要的是讓您的 EF 用戶類繼承自 IUser。

這也是@kimbaudi 建議的另一種方式。 有了這個,您不需要定義映射鍵屬性,而是可以使用自己定義的模型屬性。

public class MyObject
{
   public string UserId { get; set; }


   public ApplicationUser User { get; set; }

    // other properties
}

public class ApplicationUser : IdentityUser
{ 
    public virtual ICollection<MyObject> MyObjects { get; set; }      

}

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
    public ApplicationDbContext()
        : base("DefaultConnection", throwIfV1Schema: false)
    {
    }

    public DbSet<MyObject> MyObjects { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        modelBuilder.Entity<MyObject>()
        .HasRequired(po => po.User)
        .WithMany(a => a.MyObjects)
        .HasForeignKey(po => po.UserId);
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM