我在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 Migrations?
我可以“到后面”并通过sql语句添加外键,但如果我想从Code First再次更新,我可能会收到错误(数据库当前不匹配旧的迁移或类似的东西).
我们如何正确地使用外键参考这些会员表?
我还尝试使用AspNetUsers表的匹配属性创建一个AspNetUser类.我没有在Client类上使用“public ApplicationUser”,而是声明了“public AspNetUser”.这样做会导致迁移失败 – “未应用自动迁移,因为它会导致数据丢失”.
那么该怎么办?
解决方法
在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”.