主要的并发问题?

这是我做的一个小实验:

MyClass obj = dataContext.GetTable<MyClass>().Where(x => x.ID = 1).Single();
Console.WriteLine(obj.MyProperty); // output = "initial"
Console.WriteLine("Waiting..."); // put a breakpoint after this line
obj = null;
obj = dataContext.GetTable<MyClass>().Where(x => x.ID = 1).Single(); // same as before, but reloaded
Console.WriteLine(obj.MyProperty); // output still = "initial"
obj.MyOtherProperty = "foo";
dataContext.SubmitChanges(); // throws concurrency exception

当我在第3行后打断点时,我进入一个SQL查询窗口并手动将值更改为“updated”。 然后我继续跑步。 Linq不重新加载我的对象,但重新使用它以前在内存中的对象! 这是数据并发性的一个巨大问题!

你如何禁用Linq显然保存在内存中的对象隐藏缓存?

编辑 - 经过反思,微软在Linq框架中留下如此巨大的鸿沟简直是不可想象的。 上面的代码是我实际做的事情的一个虚拟版本,可能有一些我错过的微妙之处。 总之,如果你做自己的实验来验证我的发现是正确的,我会很感激。 或者,必须有某种“秘密交换机”才能使Linq在并发数据更新的情况下保持健壮。 但是什么?


这不是我之前遇到的问题(因为我不倾向于长时间保持DataContexts的打开状态),但它看起来像其他人一样:

http://www.rocksthoughts.com/blog/archive/2008/01/14/linq-to-sql-caching-gotcha.aspx


LinqToSql有多种工具来处理并发问题。

然而,第一步是承认有一个并发问题需要解决!

首先,DataContext预期的对象生命周期应该与UnitOfWork匹配。 如果你长时间坚持一个,那么你将不得不更努力地工作,因为这个课程不是为了这样使用而设计的。

其次,DataContext跟踪每个对象的两个副本。 一个是原始状态,一个是已更改/可更改状态。 如果您要求Id = 1的MyClass,它会让您回到它上次提供的同一个实例,这是更改后的/可更改的版本...而不是原始版本。 它必须这样做以防止在内存实例中发生并发问题... LinqToSql不允许一个DataContext知道两个可变更的MyClass版本(Id = 1)。

第三,DataContext不知道你的内存中的更改是在数据库更改之前还是之后发生的,因此无法在没有一些指导的情况下裁定并发冲突。 它看到的只是:

  • 我从数据库中读取MyClass(Id = 1)。
  • 程序员修改了MyClass(Id = 1)。
  • 我将MyClass(Id = 1)发送回数据库(查看这个sql以查看where子句中的乐观并发)
  • 如果数据库的版本与原始版本(乐观并发)相匹配,则更新将成功。
  • 如果数据库的版本与原始版本不匹配,则更新将失败并发异常。

  • 好的,现在说明问题了,下面介绍几种处理方法。

    你可以扔掉DataContext并重新开始。 对于某些人来说,这有点沉重,但至少很容易实现。

    您可以通过调用DataContext.Refresh(RefreshMode, target) (在“注释”部分中具有许多良好的并发链接的参考文档DataContext.Refresh(RefreshMode, target)来请求使用数据库值刷新原始实例或更改/可变更实例。 这将带来更改客户端,并允许您的代码解决最终结果应该是什么。

    您可以关闭dbml中的并发检查(ColumnAttribute.UpdateCheck)。 这会禁用乐观并发性,并且您的代码将压倒其他人的更改。 也很重手,也容易实现。


    将DataContext的ObjectTrackingEnabled属性设置为false。

    当ObjectTrackingEnabled设置为true时,DataContext的行为就像一个工作单元。 它将保留任何对象加载到内存中,以便它可以跟踪对它的更改。 DataContext必须记住最初加载它的对象,以了解是否进行了任何更改。

    如果您正在使用只读方案,则应关闭对象跟踪。 它可以是一个体面的表现改善。

    如果你不是在只读场景中工作,那么我不确定你为什么要这样工作。 如果你已经做了编辑,那你为什么希望它从数据库中进入修改状态?

    链接地址: http://www.djcxy.com/p/52813.html

    上一篇: major concurrency problem?

    下一篇: Conditional shortcuts in LinqToSql query