转载地址: http://www.prg-cn.com/article-4443-1.html
对象加载延迟加载
在查询某对象时,实际上你只查询该对象。不会同时自 动获取这个对象。这就是延迟加载。
例如,您可能需要查看客户数据和 订单数据。你最初不一定需要检索与每个客户有关的所有订单数据。其优点是你 可以使用延迟加载将额外信息的检索操作延迟到你确实需要检索它们时再进行。 请看下面的示例:检索出来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 以加 载此类别中未停产的产品。