LINQ体验(12)——LINQ to SQL语句之对象标识和对象加载

对象标识

  • 运行库中的对象具有唯一标识。引用同一对象的两个变量实际上是引用此对象的同一实例。你更改一个变量后,可以通过另一个变量看到这些更改。
  • 关系数据库表中数据库系统的核心是的行不具有唯一标识。由于每一行都具有唯一的主键,因此任何两行都不会共用同一键值。

实际上,通常我们是将数据从数据库中提取出来放入另一层中,应用程序在该层对数据进行处理。这就是 LINQ to SQL 支持的模型。将数据作为行从数据库中提取出来时,你不期望表示相同数据的两行实际上对应于相同的行实例。如果您查询特定客户两次,您将获得两行数据。每一行包含相同的信息。

对于对象。你期望在数据库管理系统你反复向 Dasqlserver2008安装步骤教程taContext 索取相同的信息时,它实际上会为你提供同一数据库查询语句对象实例。你将它们设计为层次结构或关系图。临清天气你希望像检索实物一样检索它们,而不希望仅仅因为你多次索要同一内容而收到大量的复制实例。

在 LINQ to SQL东北211大学名单,DataContext 管理对象标识。只要你从数据库中检索新行,该行就会由其主键记录到盛气凌人的意思标识表中,并且会创建一个新的对象。只要您检索该行,就会将原始对象实例传递回应用程序。通过这种方式,DataContext 将数据库看到的标识(即主键)的概念转换成相应语言看到的标识(即实例)的概念。应用程序只看到处于第一次检索时的状态的对象。新数据如果不同,则会被丢弃。

LINQ to SQL 使用此方法来管理本地对象的完整性,以支持开linq放式更新。由于在最初创建对象后唯一发生的更改是由应用程序做出的,因此应用程序的意向是很明确的。如数据库系统工程师果在中间阶段外部数据库技术某一方做了更改,则在调用 SubmitChanges() 时会识别出这些更改。

以上来自MSDN,的确,看了有点“正规”,下面我用两个例子说明一下。

对象缓存

在第一个示例中,如果我们执行同一查询两次,则每次都会收到对内存中同一对象的引用。很明显,cust1和cust2是同数据库系统概论第五版课后答案一个对象引用。

Customer cust1 = db.Customers.First(c => c.CustomerID == "BONAP");
Customer cust2 = db.Customers.First(c => c.CustomerID == "BONAP");

下面的示例中,如果您执行返回数据库中同一行的不同查询,则您每次都会收到对内存中同一对象的引用。宋庆玲c数据库系统的核心是ust1和cust2是同一个对象引用,但是数据库查询了两次。

Customer cust1 = db.Customers.First(c => c.CustomerID == "BONAP");
Customer cust2 = (
from o in db.Orders
where o.Customer.CustomerID == "BONAP"
select o )
.First()
.Customer;

对象加载

延迟加载

在查询某对象时,实际上你只查询该对象。不会同时自动获取这个对象。这就是延迟加载。

例如,您可能需要查看客户数据和订单数据。你豆瓣250最初不一定需要检索与每个客户有关的所有订单数据。其优点是你可以使用延迟加载将额外信息的检索操作延迟到你确实需要linq检索它们时再进行。sqlserver内存最佳配置请看下面的示例:检索出来C数据库系统的核心是ustomerID,就根据这个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) {
Console.WriteLine("CustomerID {0} has an OrderID {1}.",
cust.CustomerID, ord.OrderID);//同时查看客户数据和订单数据
}
}

LoadWith 方法:立即加载

你如果想要同时查询出一些对象的集合的方法。LINQ to SQL 提供了 DataLoadOptions用于立即加载对象。方法包括:

LoadWith 方法,用于立即加载与主目标相关的数据。
AssociateW打板2进3的技巧ith 方法,用于筛选豆瓣250为特定关系检索到的对象。

使用 LoadWith方法指定应同时检索与主目标相关的哪些数据。例如,如果你知道你需要有关客数据库设计户的订单的信息,则可以使用 LoadWith 来确保在检索客户信息的同时检索订单信息sqlserver修改字段长度。使用此linq方法可仅访问一次数据库,但同时获取两组信息。

在下面的示例中,我们通过设置DataLoadOptions,来指示DataContext在加载Customers的同时把对应的Orders一起加载,帅气撩人高冷动漫男头在执行查询时会检索位于Sao Paulo的所有 Customers 的所有 Orders神祇领主时代。这样一来,连续访问 Customer 对象的 Or数据库系统概论第五版课后答案ders 属性不会触发新的数据库查询。在数据库原理及应用执行时生成的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);
}
}

延迟加载:AssociateWith方法

使用 AssociateWith舍曲林 方法指定子查询以限制检索的数据量。

在下面孙侨潞的示例中,AssociateWith 方法将检索的 Orders 限制为当天尚未装运的那些 Orders。如果没有此方法,则会检索所有 Order盛气凌人的意思s,即使只需要一个子集。但是生成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) {
Console.WriteLine("CustomerID {0} has an OrderID {1} that ShipVia is {2} with ProductID
{3} that has name {4}.",cust.CustomerID, ord.OrderID, ord.ShipVia,
orderDetail.ProductID, orderDetail.Product.ProductName);
}
}
}

立即加载:L林七七oadWith方法和Associatsqlserver数据库e 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) {
Console.WriteLine("CustomerID {0} has an OrderID {1} with ProductID {2} that has
Quantity {3}.",cust.CustomerID, ord.OrderID, orderDetail.ProductID, orderDetail.Quantity );
}
}
}

优先加载数据库原理及应用

这个例SQL子在Category赌博200万流水能判多久类里提供了一个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)
{
Console.WriteLine("Category {0} has a ProductID {1} that Discontined = {2}.",
cat.CategoryID, prod.ProductID, prod.Discontinued);
}
}

作者:​​李永京​​(​​YJingLee's Blog​​)

​​​​​