原文鏈接:https://www.entityframeworktutorial.net/code-first/inverseproperty-dataannotations-attribute-in-code-first.aspx 當兩個實體之間不止一種關係的時候,可以使用InversePrope ...
當兩個實體之間不止一種關係的時候,可以使用InverseProperty特性,為了理解InverseProperty特性我們來做一個例子:
1.創建一個控制台應用程式,安裝好EF:
2.創建Course類:
public class Course
{
public int CourseId { get; set; }
public string CourseName { get; set; }
public string Description { get; set; }
public Teacher OnlineTeacher { get; set; }
}
3.創建Teacher類:
public class Teacher
{
public int TeacherId { get; set; }
public string Name { get; set; }
public ICollection<Course> OnlineCourses { get; set; }
}
上面的代碼例子中,Course和Teacher實體之間是一對多的關係,一個Teacher可以教很多的Online Course。
3.創建上下文類:
public class EFDbContext:DbContext
{
public EFDbContext()
: base("name=Constr")
{ }
public DbSet<Course> Courses { get; set; }
public DbSet<Teacher> Teachers { get; set; }
}
4.SQL鏈接字元串:
<!--SQL鏈接字元串-->
<connectionStrings>
<add name="Constr" connectionString="Server=.;Database=EFAnnotationInversePropertyDB;uid=sa;pwd=Password_1" providerName="System.Data.SqlClient"/>
</connectionStrings>
5.測試代碼:
class Program
{
static void Main(string[] args)
{
using (var db = new EFDbContext())
{
List<Course> lstModel = db.Courses.ToList();
}
Console.WriteLine("success");
Console.ReadKey();
}
}
6.運行程式:
可以看到,根據預設的約定,生成的資料庫如下:
現在假設Course和Teacher實體之間,還有一個一對多的關係:
Course類:
public class Course
{
public int CourseId { get; set; }
public string CourseName { get; set; }
public string Description { get; set; }
public Teacher OnlineTeacher { get; set; }
public Teacher ClassRoomTeacher { get; set; }
}
Teacher類:
public class Teacher
{
public int TeacherId { get; set; }
public string Name { get; set; }
public ICollection<Course> OnlineCourses { get; set; }
public ICollection<Course> ClassRoomCourses { get; set; }
}
在上面代碼例子中,Course和Teacher實體有兩個一對多的關係。一門課程可以被一個Online Teacher教,也可以被一個class-room Teacher教。同樣一個教師可以教多個Online Course,也可以教多個class-room Course.
刪掉之前生成的資料庫後,我們運行一下程式:
看看生成的資料庫:
看到,EF為我們在Course表中,生成了4個外鍵。為瞭解決這個問題,我們使用InverseProperty特性。修改一下Teacher類的代碼:
Teacher類:
public class Teacher
{
public int TeacherId { get; set; }
public string Name { get; set; }
[InverseProperty("OnlineTeacher")]
public ICollection<Course> OnlineCourses { get; set; }
[InverseProperty("ClassRoomTeacher")]
public ICollection<Course> ClassRoomCourses { get; set; }
}
Course類:
public class Course
{
public int CourseId { get; set; }
public string CourseName { get; set; }
public string Description { get; set; }
public Teacher OnlineTeacher { get; set; }
public Teacher ClassRoomTeacher { get; set; }
}
在上面的例子中,InverseProperty特性應用在兩個集合類型的導航屬性OnlineCourses和ClassRoomCourses上,然後指定它們在Course實體中的相關聯的導航屬性,所以現在EF就能分辨出來相應的外鍵。EF 6將創建兩個外鍵:OnlineTeacher_TeacherId
和ClassRoomTeacher_TeacherId
。對於EF Core將會創建OnlineTeacherTeacherId
和ClassRoomTeacherTeacherId
兩個外鍵。
然後在刪除資料庫,重新運行一下程式:
看一下生成的資料庫:
可以看到現在生成的資料庫就是正確的了。
進一步配置,你可以使用ForeignKey特性來配置外鍵名稱:
Course類:
public class Course
{
public int CourseId { get; set; }
public string CourseName { get; set; }
public string Description { get; set; }
[ForeignKey("OnlineTeacher")]
public int OnlineTeacherId { get; set; }
public Teacher OnlineTeacher { get; set; }
[ForeignKey("ClassRoomTeacher")]
public int ClassRoomTeacherId { get; set; }
public Teacher ClassRoomTeacher { get; set; }
}
Teacher類:
public class Teacher
{
public int TeacherId { get; set; }
public string Name { get; set; }
[InverseProperty("OnlineTeacher")]
public ICollection<Course> OnlineCourses { get; set; }
[InverseProperty("ClassRoomTeacher")]
public ICollection<Course> ClassRoomCourses { get; set; }
}
上面代碼中,我們在Corse類中添加兩個屬性列,配置外鍵,現在刪除資料庫,重新運行一下:
看到報錯了,我們修改一下Course類:
Course類最終代碼:
public class Course
{
public int CourseId { get; set; }
public string CourseName { get; set; }
public string Description { get; set; }
[ForeignKey("OnlineTeacher")]
public int? OnlineTeacherId { get; set; }
public Teacher OnlineTeacher { get; set; }
[ForeignKey("ClassRoomTeacher")]
public int? ClassRoomTeacherId { get; set; }
public Teacher ClassRoomTeacher { get; set; }
}
重新運行程式:可以看到成功了。
我們看看最終生成的資料庫:
可以看到生成的外鍵列就是我們自己自定義的名稱了。
綜上所述:當兩個實體間有多個關係的時候,你可以使用InverseProperty 特性和ForeignKey 特性來配置實體。