本文来自:http://msdn.microsoft.com/zh-cn/library/bb399393(v=vs.110).aspx
http://www.cnblogs.com/zhanglinfan/articles/1457068.html
http://hi.baidu.com/ccitofhxxxbenwq/item/b930bca05b49f57f6cd455c6
延迟加载与立即加载
查询某对象时,实际上您只检索请求的对象。 不会同时自动获取相关对象。 (有关更多信息,请参见跨关系查询。)您无法看到相关对象尚未加载这一事实,原因是尝试访问它们时将产生检索它们的请求。
例如,您可能需要查询一组特定的订单,然后偶而向特定客户发送电子邮件通知。 您最初不一定需要检索与每个订单有关的所有客户数据。 您可以使用延迟加载将额外信息的检索操作延迟到您确实需要检索它们时再进行。 请看下面的示例:
反过来也可能是可行的。 您的应用程序可能必须同时查看客户数据和订单数据。 您了解同时需要这两组数据。 您了解一旦获得结果,您的应用程序就需要每个客户的订单信息。 您不希望一个一个地提交对每个客户的订单的查询。 您真正想要的是将订单数据与客户信息一起检索出来。
Northwnd db = new Northwnd(@"c: orthwnd.mdf"); db.DeferredLoadingEnabled = false; IQueryable<Customer> custQuery = from cust in db.Customers where cust.City == "London" select cust; foreach (Customer custObj in custQuery) { foreach (Order ordObj in custObj.Orders) { ProcessCustomerOrder(ordObj); } }
您还可以在查询中联接客户和订单,方法是构建叉积并将所有相关数据位作为一个大型投影检索出来。 但这些结果并非实体。 (有关更多信息,请参见 LINQ to SQL 对象模型)。 实体是具有标识且您可以修改的对象,而这些结果将是无法更改和持久化的投影。 更糟的是,您将检索到大量的冗余数据,因为在平展联接输出中,对于每个订单,每个客户将重复出现。
您真正需要的是同时检索相关对象的集合的方法。 此集合是关系图的精确剖面,因此您检索到的数据绝不会比您所需要的数据多或少。 为此,LINQ to SQL 提供了 DataLoadOptions,用以立即加载对象模型的某一区域。 方法包括:
-
LoadWith 方法,用于立即加载与主目标相关的数据。
-
AssociateWith 方法,用于筛选为特定关系检索到的对象。
一,关于Linq延迟执行问题
var result=from c in Products
where c.Price>500
select c;
foreach(Product p in result){
Console.WriteLine(p.Name);
}
foreach(Product p in result){
Console.WriteLine(p.Name);
}
因此,对于上述程序,两个foreach语句会导致查询被执行两次,这种行为被称作
Linq延迟执行。如果使用不当,会导致各种程序效率问题,比如大量的数据绑定如果做得是Linq延迟执行,程序效率将会大大降低。
改进Linq延迟执行
var result=from c in Products
where c.Price>500
select c;
var list=result.ToList<Product>();
foreach(Product p in result){
Console.WriteLine(p.Name)
}
foreach(Product p in result){
Console.WriteLine(p.Name)
}
通过调用ToList或者ToArray方法,可以直接执行Linq查询,将查询结果缓冲再list变量中。从而可以避免Linq延迟执行的效率问题。
关于Linq中对象引用相等的问题
var result=
from c in db.Categorys
from p in c.Products
where p.ProductId=="FI-01"
select p;
// 第一次查询
Product p1=null;// 映射数据库中的一行(主键为"FI-01")
foreach(var item in result)
{
p1=item;
Console.WriteLine(item.Name);
}
// 第二次查询
Product p2=null;// 映射数据库中的一行(主键为"FI-01")
foreach(var item in result)
{
p1=item;
Console.WriteLine(item.Name);
}
Console.WriteLine(p1==p2);// p1与p2引用相等。 p1==p2相当于//object.ReferenceEquals(p1,p2)