日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

深入了解EntityFramework——Lazy Loading与Eager Loading

發布時間:2025/3/11 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 深入了解EntityFramework——Lazy Loading与Eager Loading 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

?

Lazy Loading:延遲加載。Eager Loading:貪婪加載。

首先通過一個簡單的控制臺應用程序例子說明延遲加載

訂單主表和訂單從表,并且訂單主表和訂單從表是一對多的關系,代碼如下圖所示:

//訂單主表public class Order{public int Id { get; set; }public DateTime OrderDate { get; set; }//導航屬性public virtual List<OrderDetail> OrderDetail { get; set; }} //訂單從表public class OrderDetail{public int Id { get; set; }public string ProductName { get; set; }public int Quantity { get; set; }public int Price { get; set; }public int XOrderId { get; set; }//導航屬性public virtual Order Order { get; set; }}

?Fluent API 代碼如下:

public class kTStoreModel : DbContext{public kTStoreModel(): base("name=kTStoreModel"){}protected override void OnModelCreating(DbModelBuilder modelBuilder){modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();modelBuilder.Entity<OrderDetail>().HasRequired(od => od.Order).WithMany(o => o.OrderDetail).HasForeignKey(x => x.XOrderId);}public virtual DbSet<Order> Order { get; set; }public virtual DbSet<OrderDetail> OrderDetail { get; set; }}

運行程序建立表結構后,在數據表中插入一些測試數據,并修改Main函數方法如下圖所示:

static void Main(string[] args) {using (kTStoreModel db = new kTStoreModel()){foreach (Order order in db.Order){Console.WriteLine("訂單編號:{0},訂單時間:{1}", order.Id, order.OrderDate);foreach (OrderDetail detail in order.OrderDetail){Console.WriteLine("\t名稱:{0},數量:{1},價格:{2}",detail.ProductName,detail.Quantity,detail.Price);}}Console.ReadKey();} }

再次運行程序,結果如下圖所示:

? ? ? ? ? ? ? ? ? ? ??


上述例子演示了一個簡單的查詢功能,?接下去修改Main函數中的代碼如下圖所示:

using (kTStoreModel db = new kTStoreModel()) {db.Database.Log = Console.Write;var cs = db.Order;Console.WriteLine("\n\n開始執行SQL》》\n\n");Order order = cs.First();Console.WriteLine("\n\n開始執行導航屬性 》》\n\n");List<OrderDetail> details = order.OrderDetail; } Console.ReadKey();

運行程序,執行結果如下圖所示:?

可以看到,生成了兩條SQL:第一條SQL是查詢Order數據表的,第二條SQL是查詢OrderDetail表的。載入完整的關聯數據容易造成應用程序的執行瓶頸。因此EntityFramework通過所謂的Lazy Loading避免一次載入過多的的數據內容,第一層循環并未觸及OrderDetail相關的數據,只有到第二層循環時才會載入。


使用Eager Loading

如果想采用Eager Loading預先知道加載的所有數據,包含導航屬性關聯的內容,DbSet中的Include方法支持這種加載機制,修改Main函數中的方法如下圖所示:

using (kTStoreModel db = new kTStoreModel()){db.Database.Log = Console.Write;Console.WriteLine("\n\n開始執行SQL》》\n\n");var cs = db.Order.Include("OrderDetail").Select(x => x).ToList();Console.WriteLine("\n\n開始執行導航屬性 》》\n\n");var details = cs.First().OrderDetail;}Console.ReadKey();

運行結果如下:

? ? ? ??

從上圖中可以看到程序一次性加載了所有的數據,在執行導航屬性的階段不用再去執行另外的SQL語句了。

?


調整Virual屬性?

由于EF默認為延遲加載,因此在沒有額外設置情況下都是將導航屬性設置為vriual,如此一來當明確讀取這個關聯屬性時,戶籍自動將相關數據逐一取出。如下圖代碼所示的情況,會執行兩段SQL:

using (kTStoreModel db = new kTStoreModel()) {Order order = db.Order.First();Console.WriteLine("訂單編號:{0},訂單時間:{1}", order.Id, order.OrderDate);foreach (OrderDetail detail in order.OrderDetail){Console.WriteLine("\t名稱:{0},數量:{1},價格:{2}", detail.ProductName, detail.Quantity, detail.Price);}Console.ReadKey(); }

如果刪除Order實體類中的導航屬性的Virual聲明,將不會生成第二段查詢OrderDetail的SQL,foreach循環將會報錯。

強制調用Include方法可以讓我們在一開始就取出所有的數據,但是我只需要特定數據對象時,這就會有性能浪費的問題。這種情況下,如果想要自行取出關聯的數據,可以進一步調用Load方法,調整代碼如下圖所示:

using (kTStoreModel db = new kTStoreModel()) {db.Database.Log = Console.Write;Order order = db.Order.First();db.Entry(order).Collection(c => c.OrderDetail).Load();Console.WriteLine("訂單編號:{0},訂單時間:{1}", order.Id, order.OrderDate);foreach (OrderDetail detail in order.OrderDetail){Console.WriteLine("\t名稱:{0},數量:{1},價格:{2}", detail.ProductName, detail.Quantity, detail.Price);}Console.ReadKey(); }

運行效果下圖所示:

? ? ? ? ??

?


LazyLoadingEnable屬性

除了修改實體類定義以外,比較彈性的做法是通過配置來達到相同的效果。通過配置以下代碼,關閉了Lazy Loading操作,因此不會再自動加入關聯的數據。

using (kTStoreModel db = new kTStoreModel()) {db.Configuration.LazyLoadingEnabled = false;//關閉延遲加載// etc..... }

?Include方法與對象加載

可以通過Include完整的載入導航屬性的關聯數據,對于更復雜的關聯數據,可以串聯Include方法加載更完整的數據。

假設存在如下幾個實體類:

public class Order {public int Id {get;set;}public DateTime OrderDate {get;set;}public int CustomerId{get;set;}//導航屬性public virual ICollection<OrderDetail> OrderDetails {get;set;}public virual Customer Customer{get;set;} }public class OrderDetail {public int Id{get;set;}public int OrderId {get;set;}public int ProductId{get;set;}public int Quantity {get;set;}public int Price{get;set;}//導航屬性public virtual Order Order{get;set;}public virtual Product Product{get;set;} }public class Product {public int Id{get;set;}public string Name {get;set;}public int Price {get;set;}//導航屬性public virtual ICollection<OrderDetail> OrderDetails{get;set;} }public class Customer {public int Id {get;set;}public string ContactName{get;set;}public string Phone{get;set;}public string Email{get;set;}//導航屬性public virual ICollection<Order> Orders {gets;set;} }

如果需要以客戶數據為主體,按順序輸出此客戶的所有訂單數據以及每一筆訂單的商品明細與對應的價格,可以參考如下程序:

static void Main(string[] args) {using(var context = new KTStoreModel()){context.Database.Log = Console.Write;var customer = context.Customers;foreach(var c in customer){Consolem.WriteLine("\tOrder_Id:{0}",o.Id);foreach(var o in c.Orders){Console.WriteLine("\tOrder_Id:{0}",o.Id);foreach (var od in o.OrderDetail){Console.WriteLine("\t\tProduct_Id:{0}\tPrice:{1}",od.ProductId,od.Price);}}Console.Read();}} }

?不考慮性能問題,以上的程序代碼即可完成關聯數據的列舉并以嵌套結構輸出。但是每次嵌套循環會產生大量SQL,這還不是一個好的選擇。修改程度代碼如下圖所示:

using(var context = new KTStoreModel()){context.Database.Log = Console.Write;var customer = context.Customers.Include("Orders.OrderDetails").Include("Orders.OrderDetails.Product");foreach(var c in customer){Consolem.WriteLine("\tOrder_Id:{0}",o.Id);foreach(var o in c.Orders){Console.WriteLine("\tOrder_Id:{0}",o.Id);foreach (var od in o.OrderDetail){Console.WriteLine("\t\tProduct_Id:{0}\tPrice:{1}",od.ProductId,od.Price);}}Console.Read();}}

更進一步,使用Where篩選數據可以進一步避免返回不需要的數據,如下圖所示:

var customer = context.Customers.Include("Orders.OrderDetails").Include("Orders.OrderDetails.Product").Where(c => c.Id < 5)

?

?

?

?

?

?

?

?

總結

以上是生活随笔為你收集整理的深入了解EntityFramework——Lazy Loading与Eager Loading的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。