Linq to Sql update中的ChangeConflictException

时间:2009-03-19 20:03:30

标签: linq-to-sql

我正处在这个痛苦的世界里,如果有人可以提供帮助,我会非常感激。

我有一个DataContext附加到数据库上的单个测试表。测试表如下:

CREATE TABLE [dbo].[LinqTests](
    [ID] [bigint] IDENTITY(1,1) NOT NULL,
    [StringValue] [varchar](255) NOT NULL,
    [DateTimeValue] [datetime] NOT NULL,
    [BooleanValue] [bit] NOT NULL,
    CONSTRAINT [PK_LinqTests] PRIMARY KEY CLUSTERED ([ID] ASC))
ON [PRIMARY]

使用Linq,我可以添加,检索和删除测试表中的行,但是我无法更新行 - 对于UPDATE,我总是得到一个带有空ObjectChangeConflict.MemberConflicts集合的ChangeConflictException。以下是使用的代码:

var dataContext = new UniversityDataContext();
dataContext.Log = Console.Out;

for (int i = 1; i <= 1; i++) {
    var linqTest = dataContext.LinqTests.Where(l => (l.ID == i)).FirstOrDefault();

    if (null != linqTest) {
        linqTest.StringValue += " I've been updated.";
    }
    else {
        linqTest = new LinqTest {
            BooleanValue = false,
            DateTimeValue = DateTime.UtcNow,
            StringValue = "I am in loop " + i + "."
        };
        dataContext.LinqTests.InsertOnSubmit(linqTest);
    }
}

try {
    dataContext.SubmitChanges(ConflictMode.ContinueOnConflict);
}
catch (ChangeConflictException exception) {
    Console.WriteLine("Optimistic concurrency error.");
    Console.WriteLine(exception.Message);
    Console.ReadLine();
}

Console.ReadLine();

以下是通过DataContext执行更新的日志输出。

UPDATE [dbo].[LinqTests]
SET [StringValue] = @p3
WHERE ([ID] = @p0) AND ([StringValue] = @p1) AND ([DateTimeValue] = @p2) AND (NOT ([BooleanValue] = 1))
-- @p0: Input BigInt (Size = 0; Prec = 0; Scale = 0) [1]
-- @p1: Input VarChar (Size = 15; Prec = 0; Scale = 0) [I am in loop 1.]
-- @p2: Input DateTime (Size = 0; Prec = 0; Scale = 0) [3/19/2009 7:54:26 PM]
-- @p3: Input VarChar (Size = 34; Prec = 0; Scale = 0) [I am in loop 1. I've been updated.]
-- Context: SqlProvider(Sql2000) Model: AttributedMetaModel Build: 3.5.30729.1

我正在群集SQL Server 2000(8.0.2039)上运行此查询。我不能,为了我的生活,弄清楚这里发生了什么。对数据库运行类似的UPDATE查询似乎工作正常。

提前感谢您的帮助。

4 个答案:

答案 0 :(得分:28)

我终于弄明白了这件事发生了什么。显然,此服务器已启用“无计数”选项。

在Microsoft SQL Server Management Studio 2005中:

  1. 右键单击服务器,然后单击属性
  2. 在“服务器属性”窗口的左侧,选择连接页面
  3. 在默认连接选项下,确保未选择“无计数”。
  4. 显然,LINQ to SQL在更新后使用@@ ROWCOUNT来发出自动乐观并发检查。当然,如果为整个服务器启用“无计数”,则@@ ROWCOUNT始终返回零,并且LINQ to SQL在向数据库发出更新后抛出ConcurrencyException。

    这不是LINQ to SQL使用的唯一更新行为。如果您的表上有TIMESTAMP列,则LINQ to SQL不会使用@@ ROWCOUNT执行自动乐观并发检查。

答案 1 :(得分:1)

该行的任何数据在检索和尝试更新之间是否有可能发生变化?因为LINQ-&gt; SQL具有自动并发检查功能,它将根据当前存储的值验证对象的内容(就像您在生成的查询中看到的那样)。如果DB中的行与LINQ正在跟踪的对象的任何字段有可能已更改,则更新将失败。如果这种情况发生并且有充分理由并且您知道哪些字段,则可以更新DBML设计器中的对象;选择原因中的字段并将“更新检查”属性更改为“从不”。

答案 2 :(得分:1)

我遇到了与SQL Server 2008相同的问题,连接选项no count 已经转为

我没有将Update Check属性更改为从不(如Quintin建议的那样),而是将其设置为 WhenChanged 并解决了问题。

答案 3 :(得分:0)

首先记录有关问题的详细信息,哪些行和哪些字段存在冲突以及哪些值存在冲突。

要实现此类详细日志,请参阅我的解决方案:

What can I do to resolve a "Row not found or changed" Exception in LINQ to SQL on a SQL Server Compact Edition Database?