[英]'Microsoft.AspNet.Identity.EntityFramework.IdentityUser' is not marked as serializable
[英]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”。 這樣做會導致遷移失敗 - “未應用自動遷移,因為它會導致數據丟失。”
那么,該怎么辦?
在ApplicationUser
和MyObject
之間創建一對多關系並在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
類型, ApplicationUser
的ID
也是如此!
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.