跨不同的Linq-to-SQL上下文的实体相等性

本文关键字:实体 Linq-to-SQL 上下文 | 更新日期: 2023-09-27 18:07:50

我试图在我创建的WPF应用程序中添加一些多线程,以便创建一个响应更快的界面,但由于Linq-to-SQL数据上下文不是线程安全的,我被迫每个线程使用一个。

我的问题是同一个实体从两个不同的上下文中拉出来,显然是不相等的。以以下代码示例为例,其中我有一个包含员工记录的简单数据库:

var context1 = new DataModelDataContext();
var context2 = new DataModelDataContext();
var emp1 = context1.Employees.Single(x => x.ID == 1);
var emp2 = context2.Employees.Single(x => x.ID == 1);
Console.WriteLine(string.Format("Employees equal: {0}", emp1 == emp2));
Console.ReadKey();

当运行时,返回:

Employees equal: False

在我的脑海中,我希望这些对象是相等的,因为如果我从相同的上下文中提取它们。我可以通过检查emp1来克服这个问题。ID == emp2。ID,但是当尝试使用WPF绑定(如SelectedItem)时会出现问题。

有别的办法吗?

跨不同的Linq-to-SQL上下文的实体相等性

两个独立实例化的对象可能表示数据存储中的同一项,但它们在任何语言中都不会计算为相等。您必须编写代码来比较每个对象的成员,以确定它们的数据是否相等。这可能像比较主键那样简单,也可能不像比较主键那么简单。

您总是可以覆盖EqualsGetHasCode,以确保对象是"相等的",即使它们不是相同的实例(这是用于引用类型的默认相等规则)

如@cdonner所述,当您从数据存储中加载对象时,将使用相同的数据创建该对象的两个不同实例。这将意味着object1 != object2.

克服这个问题的一种方法是在存储库中设置一个类似dictionary的缓存。例如:Dictionary<Type, object>其中object是标识符的类型(在本例中为int)

与其使用context1.Employees.Single(x => x.ID == 1);这样的内联代码来查询数据存储不如将其设置为Repositories.Employees.WithID(1);

这将做的是检查本地存储库缓存中的Employee对象与ID == 1,如果这是可用的返回它而不是查询数据存储。

从那时起,你的引用将永远是相同的。

当您想要从数据存储更新和刷新内存中的对象时,这可能需要一些改进,以便您不会持久保存过时的数据,并且当您从数据存储中刷新数据时,您会更新缓存。