Jac*_*ack 36 asp.net-mvc entity-framework foreign-keys foreign-key-relationship ef-code-first
我的MVC应用程序中有两个实体,我使用Entity Framework 6 Code First方法填充数据库.学生实体中有两个城市ID; 其中一个为BirthCity,另一个为WorkingCity.当我在上面定义外键时,在迁移后在Student表中创建一个名为City_ID的额外列.我有错误或如何定义这些FK?提前致谢.
学生:
public class Student
{
public int ID { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
public int BirthCityID { get; set; }
public int LivingCityID { get; set; }
[ForeignKey("BirthCityID")]
public virtual City BirthCity { get; set; }
[ForeignKey("LivingCityID")]
public virtual City LivingCity { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
市:
public class City
{
public int ID { get; set; }
public string CityName { get; set; }
public virtual ICollection<Student> Students { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
oct*_*ccl 58
要实现您想要的功能,您需要提供一些aditional configuration.Code第一个约定可以识别双向关系,但不能在两个实体之间存在多个双向关系时.您可以添加配置(使用Data Annotations或Fluent API)来显示此信息到模型构建者.使用Data Annotations,您将使用一个名为的注释InverseProperty.使用Fluent API,您将使用Has/ Withmethods 的组合来指定这些关系的正确结束.
使用数据注释可以是这样的:
public class Student
{
public int ID { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
public int BirthCityID { get; set; }
public int LivingCityID { get; set; }
[ForeignKey("BirthCityID")]
[InverseProperty("Students")]
public virtual City BirthCity { get; set; }
[ForeignKey("LivingCityID")]
public virtual City LivingCity { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
这样,您明确指定要将BirthCity导航属性与Students关系另一端的导航属性相关联.
使用Fluent Api可能是这样的:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Student>().HasRequired(m => m.BirthCity)
.WithMany(m => m.Students).HasForeignKey(m=>m.BirthCityId);
modelBuilder.Entity<Student>().HasRequired(m => m.LivingCity)
.WithMany().HasForeignKey(m=>m.LivingCityId);
}
Run Code Online (Sandbox Code Playgroud)
使用最后一个解决方案,您无需使用任何属性.
现在,@ChristPratt的建议Student在你的City班级中为每个关系都有一个集合是非常有用的.如果您这样做,那么使用Data Annotations的配置可能是这样的:
public class Student
{
public int ID { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
public int BirthCityID { get; set; }
public int LivingCityID { get; set; }
[ForeignKey("BirthCityID")]
[InverseProperty("BirthCityStudents")]
public virtual City BirthCity { get; set; }
[ForeignKey("LivingCityID")]
[InverseProperty("LivingCityStudents")]
public virtual City LivingCity { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
或者使用Fluent Api遵循相同的想法:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Student>().HasRequired(m => m.BirthCity)
.WithMany(m => m.BirthCityStudents).HasForeignKey(m=>m.BirthCityId);
modelBuilder.Entity<Student>().HasRequired(m => m.LivingCity)
.WithMany(m => m.LivingCityStudents).HasForeignKey(m=>m.LivingCityId);
}
Run Code Online (Sandbox Code Playgroud)
Chr*_*att 18
啧.这是漫长的一天.实际上,你的代码实际上存在一个非常大的,明显的问题,当我评论时,我完全错过了.
问题是你正在使用一个学生集合City.这里实际发生的是EF无法决定它应该将该集合实际映射到哪个外键,因此它会创建另一个外键来专门跟踪该关系.然后,实际上你没有导出来自BirthCity和的学生集合的导航属性LivingCity.
为此,您必须下拉到流畅的配置,因为没有办法仅使用数据注释来正确配置.您还需要一个额外的学生集合,以便您可以跟踪这两种关系:
public class City
{
...
public virtual ICollection<Student> BirthCityStudents { get; set; }
public virtual ICollection<Student> LivingCityStudents { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
然后,为Student:
public class Student
{
...
public class StudentMapping : EntityTypeConfiguration<Student>
{
public StudentMapping()
{
HasRequired(m => m.BirthCity).WithMany(m => m.BirthCityStudents);
HasRequired(m => m.LivingCity).WithMany(m => m.LivingCityStudents);
}
}
}
Run Code Online (Sandbox Code Playgroud)
最后在你的背景下:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new Student.StudentMapping());
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
42742 次 |
| 最近记录: |