对象标识

运行时中的对象具有唯一标识。 引用同一对象的两个变量实际上引用了该对象的同一实例。 因此,通过一个变量的路径进行的更改会立即通过另一个变量可见。

关系数据库表中的行没有唯一标识。 由于每行都有唯一的主键,因此没有两行共享相同的键值。 但是,此事实仅限制数据库表的内容。

实际上,数据最常被带出数据库并进入另一层,其中应用程序使用它。 这是 LINQ to SQL 支持的模型。 当数据作为行从数据库中取出时,你并不期望表示相同数据的两行实际上对应于同一行实例。 如果查询特定客户两次,则会收到两行数据。 每行都包含相同的信息。

对于对象,您的期望则大不一样。 你预计,如果重复请求 DataContext 相同的信息,它实际上会提供相同的对象实例。 你期望此行为,因为对象对应用程序具有特殊意义,并且你期望它们的行为与对象类似。 你将其设计为层次结构或图形。 您希望像检索实物一样检索它们,而不希望仅仅因为您多次索要同一内容而收到大量的复制实例。

在 LINQ to SQL 中 DataContext ,管理对象标识。 每当从数据库中检索新行时,该行将按其主键记录在标识表中,并创建新对象。 每当检索同一行时,原始对象实例将移交给应用程序。 通过这种方式,将 DataContext 数据库(即主键)看到的标识概念转换为语言(即实例)看到的标识概念。 应用程序仅看到其首次检索到的状态中的对象。 如果新数据不同,将被丢弃。 有关详细信息,请参阅 从标识缓存检索对象

LINQ to SQL 使用此方法管理本地对象的完整性,以支持乐观更新。 由于首次创建对象后发生的唯一更改是应用程序所做的更改,因此应用程序的意图是明确的。 如果在此期间有外部方的变化发生,则会在调用 SubmitChanges() 时识别这些更改。

注释

如果查询请求的对象很容易识别为已检索的对象,则不会执行任何查询。 标识表充当以前检索的所有对象的缓存。

例子

对象缓存示例 1

在此示例中,如果执行同一查询两次,则每次都会在内存中收到对同一对象的引用。

Customer cust1 =
    (from cust in db.Customers
     where cust.CustomerID == "BONAP"
     select cust).First();

Customer cust2 =
    (from cust in db.Customers
     where cust.CustomerID == "BONAP"
     select cust).First();
Dim cust1 As Customer = _
    (From cust In db.Customers _
     Where cust.CustomerID = "BONAP" _
     Select cust).First()

Dim cust2 As Customer = _
    (From cust In db.Customers _
     Where cust.CustomerID = "BONAP" _
     Select cust).First()

对象缓存示例 2

在此示例中,如果执行从数据库返回同一行的不同查询,则每次都会在内存中收到对同一对象的引用。

Customer cust1 =
    (from cust in db.Customers
     where cust.CustomerID == "BONAP"
     select cust).First();

Customer cust2 =
    (from ord in db.Orders
     where ord.Customer.CustomerID == "BONAP"
     select ord).First().Customer;
Dim cust1 As Customer = _
    (From cust In db.Customers _
     Where cust.CustomerID = "BONAP" _
     Select cust).First()

Dim cust2 As Customer = _
    (From ord In db.Orders _
     Where ord.Customer.CustomerID = "BONAP" _
     Select ord).First().Customer

另请参阅