對象載入
延遲載入
在查詢某物件時,實際上你只查詢該物件。不會同時自動獲取這個物件。這就是延遲載入。
例如,您可能需要查看客戶資料和訂單資料。你最初不一定需要檢索與每個客戶有關的所有訂單資料。其優點是你可以使用延遲載入將額外資訊的檢索操作延遲到你確實需要檢索它們時再進行。請看下面的示例:檢索出來CustomerID,就根據這個ID查詢出OrderID。
var custs = from c in db.Customers where c.City == "Sao Paulo" select c; //上面的查詢句法不會導致語句立即執行, //僅僅是一個描述性的語句,只有需要的時候才會執行它 foreach (var cust in custs) { foreach (var ord in cust.Orders) { //同時查看客戶資料和訂單資料 } }
語句描述:原始查詢未請求資料,在所檢索到各個物件的連結中導航如何能導致觸發對資料庫的新查詢。
預先載入:LoadWith 方法
你如果想要同時查詢出一些物件的集合的方法。LINQ to SQL 提供了 DataLoadOptions用於立即載入物件。方法包括:
LoadWith 方法,用於立即載入與主目標相關的資料。
AssociateWith 方法,用於篩選為特定關係檢索到的物件。
使用 LoadWith方法指定應同時檢索與主目標相關的哪些資料。例如,如果你知道你需要有關客戶的訂單的資訊,則可以使用 LoadWith 來確保在檢索客戶資訊的同時檢索訂單資訊。使用此方法可僅訪問一次資料庫,但同時獲取兩組資訊。
在下面的示例中,我們通過設置DataLoadOptions,來指示DataContext在載入Customers的同時把對應的Orders一起載入,在執行查詢時會檢索位於Sao Paulo的所有 Customers 的所有 Orders。這樣一來,連續訪問 Customer 物件的 Orders 屬性不會觸發新的資料庫查詢。在執行時生成的SQL語句使用了左連接。
NorthwindDataContext db = new NorthwindDataContext(); DataLoadOptions ds = new DataLoadOptions(); ds.LoadWith<Customer>(p => p.Orders); db.LoadOptions = ds; var custs = ( from c in db2.Customers where c.City == "Sao Paulo" select c); foreach (var cust in custs) { foreach (var ord in cust.Orders) { Console.WriteLine("CustomerID {0} has an OrderID {1}.", cust.CustomerID,ord.OrderID); } }
語句描述:在原始查詢過程中使用 LoadWith 請求相關資料,以便稍後在檢索到的各個物件中導航時不需要對資料庫進行額外的往返。
延遲載入:AssociateWith方法
使用 AssociateWith 方法指定子查詢以限制檢索的資料量。
在下面的示例中,AssociateWith 方法將檢索的 Orders 限制為當天尚未裝運的那些 Orders。如果沒有此方法,則會檢索所有 Orders,即使只需要一個子集。但是生成SQL語句會發現生成了很多SQL語句。
NorthwindDataContext db2 = new NorthwindDataContext(); DataLoadOptions ds = new DataLoadOptions(); ds.AssociateWith<Customer>( p => p.Orders .Where(o => o.ShipVia > 1)); db2.LoadOptions = ds; var custs = from c in db2.Customers where c.City == "London" select c; foreach (var cust in custs) { foreach (var ord in cust.Orders) { foreach (var orderDetail in ord.OrderDetails) { //可以查詢出cust.CustomerID, ord.OrderID, ord.ShipVia, //orderDetail.ProductID, orderDetail.Product.ProductName } } }
語句描述:原始查詢未請求資料,在所檢索到各個物件的連結中導航如何以觸發對資料庫的新查詢而告終。此示例還說明在延遲載入關係物件時可以使用 Assoicate With 篩選它們。
預先載入:LoadWith方法和Associate With方法
這個例子說明:使用LoadWith方法來確保在檢索客戶資訊的同時檢索訂單資訊,在檢索訂單資訊的同時檢索訂單詳細資訊, 僅僅訪問一次資料庫。即可以在一個查詢中檢索許多物件。使用Associate With方法來限制訂單詳細資訊的排序規則。
NorthwindDataContext db2 = new NorthwindDataContext(); DataLoadOptions ds = new DataLoadOptions(); ds.LoadWith<Customer>(p => p.Orders); ds.LoadWith<Order>(p => p.OrderDetails); ds.AssociateWith<Order>( p => p.OrderDetails .OrderBy(o => o.Quantity)); db2.LoadOptions = ds; var custs = ( from c in db2.Customers where c.City == "London" select c); foreach (var cust in custs) { foreach (var ord in cust.Orders) { foreach (var orderDetail in ord.OrderDetails) { //查詢cust.CustomerID, ord.OrderID //orderDetail.ProductID, orderDetail.Quantity } } }
語句描述:在原始查詢過程中使用 LoadWith 請求相關資料,以便稍後在檢索到的各個物件中導航時此示例還說明在急切載入關係物件時可以使用 Assoicate With 對它們進行排序。
加載重寫
這個例子在Category類裡提供了一個LoadProducts分部方法。當產品的類別被載入的時候,就直接優先調用了LoadProducts方法來查詢沒有貨源的產品。
private IEnumerable<Product> LoadProducts(Category category) { //在執行LINQ to SQL的時候,這個LoadProducts分部方法 //優先載入執行,這裡用存儲過程也可以. return this.Products .Where(p => p.CategoryID == category.CategoryID) .Where(p => !p.Discontinued); }
執行下面的查詢時,利用上面方法返回的資料進行下面的操作:
NorthwindDataContext db2 = new NorthwindDataContext(); DataLoadOptions ds = new DataLoadOptions(); ds.LoadWith<Category>(p => p.Products); db2.LoadOptions = ds; var q = ( from c in db2.Categories where c.CategoryID < 3 select c); foreach (var cat in q) { foreach (var prod in cat.Products) { //查詢cat.CategoryID, prod.ProductID } }語句描述:重寫 Category 類中的分部方法 LoadProducts。載入某種類別的產品時,調用 LoadProducts 以載入此類別中未停產的產品。