在 Entity Framework 中什麼是實體 Entity
在 EF 中一個實體就是程序域中的一個類,它在繼承的上下文類中包含在 DbSet<TEntity>
中作爲類型屬性。EF API 把每一個實體映射到一張表,把實體的每一個屬性映射到數據庫中的列。
例如,在 school 程序中下面的Student
,StudentAddress
和Grade
是域類。
public class Student
{
public int StudentID { get; set; }
public string StudentName { get; set; }
public DateTime? DateOfBirth { get; set; }
public byte[] Photo { get; set; }
public decimal Height { get; set; }
public float Weight { get; set; }
public StudentAddress StudentAddress { get; set; }
public Grade Grade { get; set; }
}
public partial class StudentAddress
{
public int StudentID { get; set; }
public string Address1 { get; set; }
public string Address2 { get; set; }
public string City { get; set; }
public string State { get; set; }
public Student Student { get; set; }
}
public class Grade
{
public int GradeId { get; set; }
public string GradeName { get; set; }
public string Section { get; set; }
public ICollection<Student> Students { get; set; }
}
上面的這些類當它們在上下文類(繼承自DbContext
)中被包含在DbSet<TEntity>
中作爲屬性時,它們就變成了實體,如下所示。
public class SchoolContext : DbContext
{
public SchoolContext()
{
}
public DbSet<Student> Students { get; set; }
public DbSet<StudentAddress> StudentAddresses { get; set; }
public DbSet<Grade> Grades { get; set; }
}
在上面的上下文類中,Students
,StudentAddresses
, 和 Grades
屬性的類型 DbSet<TEntity>
被稱爲實體集。Student
,,StudentAddress
,,和Grade
是實體 (也叫實體類型)。
一個實體(Entity)可以包含兩種類型的屬性:標量屬性(Scalar Properties)和導航屬性(Navigation Properties)。
標量屬性(Scalar Properties):
基本類型的屬性稱爲標量屬性。一個標量屬性可以存儲實際的數據。一個標量屬性可以映射到數據庫表的一個列。
導航屬性(Navigation Properties):
導航屬性代表和另一個實體之間的關係。
有兩種類型的導航屬性:引用導航(Reference Navigation)和集合導航(Collection Navigation)
引用導航屬性(Reference Navigation Property):
如果一個實體中包含一個實體類型的屬性,這個屬性就叫引用導航屬性。它代表多箇中的一個。
集合導航屬性(Collection Navigation Property):
如果一個實體包含一個集合類型的屬性,這個屬性就叫集合導航屬性。它代表多箇中的多個。
下面的圖表解釋了實體的屬性:
實體的類型
Entity Framework 中的實體類型:
在Entity Framework 中有兩種實體類型:簡單對象實體(POCO Entities)和動態代理實體(Dynamic Proxy Entities)。
簡單對象實體(Pain Old CLR Object):
一個簡單對象實體是一個類,它不依賴於特定框架的中基類。它和任何 .NET CLR 中的類一樣,這就是它被稱爲簡單對象實體的原因。
簡單對象實體在 EF 6 和 EF Core 中都被支持。
Entity Data Model 中生成的實體類型的查詢,插入,更新和刪除中的大多數行爲,在簡單對象實體(也叫持久無關對象)中是一模一樣的。下面是一個 Student 簡單對象實體的一個例子。
public class Student
{
public int StudentID { get; set; }
public string StudentName { get; set; }
public DateTime? DateOfBirth { get; set; }
public byte[] Photo { get; set; }
public decimal Height { get; set; }
public float Weight { get; set; }
public StudentAddress StudentAddress { get; set; }
public Grade Grade { get; set; }
}
動態代理實體(Dynamic Proxy Entities):
動態代理是一個封裝了簡單對象實體的運行時代理類。動態代理實體允許延遲加載(lazy loading)。
注意:只在 EF 6 中支持,在 EF Core 2.0 中暫時不支持。
一個簡單對象實體必須滿足一下條件才能成爲一個簡單對象代理:
- 一個簡單對象類必須聲明成 public 訪問。
- 一個簡單對象類必須不能是 sealed (在 Visual Basic 是 NotInheritable )。
- 一個簡單對象類必須不能是 abstract (在 Visual Basic 是 MustInherit )。
- 每一個導航屬性必須聲明成 public,virtual。
- 每一個集合屬性必須是
ICollection<T>
。 - 在上下文類中 ProxyCreationEnabled 選項不能是 false (默認是 true)。
下面的簡單對象實體滿足了上面的所有要求,在運行時可以變成一個動態代理實體。
public class Student
{
public int StudentID { get; set; }
public string StudentName { get; set; }
public DateTime? DateOfBirth { get; set; }
public byte[] Photo { get; set; }
public decimal Height { get; set; }
public float Weight { get; set; }
public virtual StudentAddress StudentAddress { get; set; }
public virtual Grade Grade { get; set; }
}
注意:默認情況下,每一個實體的動態代理是打開的。然而,你可以在上下文類中通過設置context.Configuration.ProxyCreationEnabled = false;
來關閉動態代理。
在運行時, EF API 將會爲上面的 Student
實體創建一個動態代理的實例。Student
的動態代理類型將會是System.Data.Entity.DynamicProxies.Student
,如下所示:
使用`ObjectContext.GetObjectType()可以找到被動態代理封裝在底層的類型,如下所示:
實體狀態
Entity States in Entity Framework:
EF API 維持每一個實體聲明週期期間的狀態。通過上下文對每一個實體執行操作時都會有一個狀態。在 EF 6 中,實體的狀態用枚舉類型System.Data.Entity.EntityState
表示,在 EF Core 中用枚舉類型Microsoft.EntityFrameworkCore.EntityState
表示。這些枚舉類型有如下值:
- Added
- Modified
- Deleted
- Unchanged
- Detached
一旦上下文從數據庫中檢索數據,它就會保持所有實體對象的引用,也會保持對實體狀態的跟蹤維護隊實體屬性所作的修改。這個特性就叫做改變跟蹤(Change Tracking)。
實體狀態從 Unchanged 轉變成 Modified 狀態是唯一個由上下文自動完成情形。所有其它的改變必須顯式地使用合適的DbContext
或者 DbSet
中的方法。
EF API 在 context.SaveChanges()
被調用時會根據實體狀態創建並執行 INSERT,UPDATE,和 DELETE 命令。它對 Added 狀態的實體執行 INSERT 命令,對 Modified 狀態的實體執行 UPDATE 命令,對 Deleted 狀態的實體執行 DELETE 命令。上下文跟蹤 Detached 狀態的實體。下面圖表解釋了狀態實體的重要性:
因此,實體狀態在 Entity Framework 中扮演了一個很重要的角色。