LINQ冲突检测:设置UpdateCheck属性

时间:2009-03-26 14:01:23

标签: linq .net-3.5 conflict updatecheck

我最近一直在阅读LINQ以开始实现它,并且关于它如何生成困扰我的UPDATE查询有一个特殊的事情。

使用SQLMetal或对象关系设计器自动创建实体代码,显然所有表的所有字段都将获得属性 UpdateCheck.Always ,这意味着对于每个UPDATE和DELETE查询,我都会得到像这样的SQL语句:

UPDATE table SET a = 'a' WHERE a='x' AND b='x' ... AND z='x', ad infinitum

现在,称我为纯粹主义者,但这对我来说似乎非常低效,无论如何这感觉都是一个坏主意,即使它不是低效的。我知道fetch将由聚簇主键完成,因此速度并不慢,但SQL仍然需要在此之后检查每个字段以确保它匹配。

当然,在一些非常敏感的应用程序中,这样的东西可能很有用,但对于典型的Web应用程序(想想Stack Overflow),似乎 UpdateCheck.WhenChanged 是更合适的默认应用程序,并且我个人更喜欢 UpdateCheck.Never ,因为LINQ只会更新已更改的实际字段,而不是所有字段,并且在大多数情况下,第二个人编辑的内容仍会获胜。

这确实意味着如果两个人在读取该行和触发UPDATE之间的小时间内设法编辑同一行的相同字段,那么将不会触发将发现的冲突。但实际上这是一个非常罕见的案例。当两个人改变相同的东西时我们可能想要防范的一件事不会被这个抓住,因为他们不会在同一时间单击提交,因此在第二个DataContext时不会发生冲突读取并更新记录(除非DataContext保持打开状态并在显示页面时存储在Session中,或者其他一些非常糟糕的想法)。

然而,尽管很少见,但我真的很想在我的代码中不时出现异常,如果发生这种情况。

所以我的第一个问题是,相信这个我错了吗? (同样,对于“典型”的网络应用程序,不适用于银行应用程序) 我错过了一些理由为什么将UpdateCheck.Always作为默认值是理智的想法?

我的第二个问题是,我可以文明地改变这个吗?有没有办法告诉SQLMetal或ORD要设置哪个UpdateCheck属性?
我试图避免这种情况,我必须记住运行一个工具,我将不得不使用一些正则表达式并直接编辑文件中的所有属性,因为很明显,在某些时候我们会运行在更新数据库之后的SQLMetal,我们将不会运行此工具,并且我们的所有代码都将以非常微妙的方式中断,这些方式在我们开发时可能无法找到。

有什么建议吗? 战争故事非常受欢迎,我很乐意从其他人的经验中学习。

非常感谢!

1 个答案:

答案 0 :(得分:2)

嗯,回答第一个问题 - 我同意你的看法。我不是这种“内置”乐观并发的忠实粉丝,特别是如果您有时间戳列或任何更新后不保证相同的字段。

要解决第二个问题 - 我不知道有什么方法可以覆盖SqlMetal的默认方法(UpdateCheck = Always),我们最终编写了一个工具,为适当的列设置UpdateCheck = Never。我们使用批处理文件来调用SqlMetal,然后运行该工具。

哦,虽然我想到了它 - 但是发现SqlMetal还建模关系以将外键设置为null而不是“Delete On Null”(特别是对于连接表)也是一种享受。我们必须使用相同的后期生成工具来适当地设置它们。