眾所周知在EF 6 及以前的版本中,是支持懶載入(Lazy Loading)的,可惜在EF Core 並不支持,必須使用 方法來支持導航屬性的數據載入。不過現在EF Core的開發團隊打算恢復對這一功能的支持(目前還未發佈,不過可以在Github上面下載進行測試)。 懶載入 懶載入也可以叫做按需載入 ...
眾所周知在EF 6 及以前的版本中,是支持懶載入(Lazy Loading)的,可惜在EF Core 並不支持,必須使用Include
方法來支持導航屬性的數據載入。不過現在EF Core的開發團隊打算恢復對這一功能的支持(目前還未發佈,不過可以在Github上面下載進行測試)。
懶載入
懶載入也可以叫做按需載入、延遲載入。可以分兩方面來理解,一方面指暫時不需要該數據,不用在當前馬上載入,而可以推遲到使用它時再載入;另一方面指不確定是否將會需要該數據,所以暫時請不要載入,待確定需要後再載入它。懶載入是一種很重要的數據訪問特性,可以有效地減少與數據源的交互(註意,這裡所提的交互不是指交互次數,而是指交互的數據量),從而提升程式性能。
EF 6 懶載入
我們先來看一看在EF 6中的懶載入的使用方式。
實體定義:
public class Order
{
public int OrderID { get; set; }
public string CustomerID { get; set; }
public DateTime? OrderDate { get; set; }
public virtual ICollection<OrderDetail> OrderDetails { get; set; }
}
public class OrderDetail
{
public int OrderID { get; set; }
public int ProductID { get; set; }
public decimal UnitPrice { get; set; }
public short Quantity { get; set; }
public float Discount { get; set; }
public virtual Order Order { get; set; }
}
我們在這裡定義訂單、訂單明細實體,它們是一對多關係,通過OrderId
欄位進行關聯。
using (NorthwindContext context = new NorthwindContext()) {
Order order = await context.Orders.SingleAsync(item => item.OrderID == 10253);
Assert.NotNull(order);
Assert.NotNull(order.OrderDetails);
Assert.Equal(3, order.OrderDetails.Count);
}
}
在查詢訂單號為 10253 的訂單後,如果我們需要訪問訂單的明細,不需要再編寫一次數據查詢的代碼,直接訪問導航屬性即可,EF會自動幫我們填充屬性的值。
懶載入需要註意以下兩點:
- 在配置中啟用了懶載入(預設開啟);
- 實體類不能是封閉(
sealed
)類,導航屬性必須是虛(virtual
)屬性。
在 EF Core 中啟用懶載入
目前EF Core發佈的最新版本中並不支持懶載入,開發人員必須使用Include
方法,才能完成導航屬性的載入。
using (NorthwindContext context = new NorthwindContext()) {
Order order = await context.Orders.Include(e => e.OrderDetails).SingleAsync(item => item.OrderID == 10253);
Assert.NotNull(order);
Assert.NotNull(order.OrderDetails);
Assert.Equal(3, order.OrderDetails.Count);
}
大家需要在Github上面下載最新的源代碼來測試這一功能 aspnet/EntityFrameworkCore。
啟用懶載入:
public class NorthwindContext : DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
var sqlConnectionStringBuilder = new SqlConnectionStringBuilder {
DataSource = "****",
InitialCatalog = "Northwind",
UserID = "sa",
Password = "sa"
};
optionsBuilder.UseSqlServer(sqlConnectionStringBuilder.ConnectionString);
optionsBuilder.UseLazyLoadingProxies();
base.OnConfiguring(optionsBuilder);
}
}
要在通常的應用程式中使用,只需在DbContext
的OnConfiguring
方法中添加對UseLazyLoadingProxies()
擴展方法調用即可。
框架目前是通過Castle.Core
框架來生成代理類來實現對導航屬性的延遲載入,開發團隊打算將該功能做為EF Core的可選安裝包。
如果您對該功能感興趣,可以在Github上面下載源代碼進行測試。