【问题标题】:ChangeConflictException in Linq to Sql updateLinq to Sql 更新中的 ChangeConflictException
【发布时间】:2009-03-19 20:03:29
【问题描述】:

我为此感到痛苦,如果有人能提供帮助,我将不胜感激。

我有一个 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 查询似乎可以正常工作。

提前感谢您的帮助。

【问题讨论】:

  • 请发布您用于更新的代码

标签: linq-to-sql


【解决方案1】:

我终于明白这是怎么回事了。显然,此服务器的“不计数”选项已打开。

在 Microsoft SQL Server Management Studio 2005 中:

  1. 右键单击服务器并单击属性
  2. 在“服务器属性”窗口的左侧,选择连接页面
  3. 在默认连接选项下,确保未选择“无计数”。

显然,LINQ to SQL 在更新后使用@@ROWCOUNT 来发出自动乐观并发检查。当然,如果为整个服务器开启“无计数”,@@ROWCOUNT 总是返回零,并且 LINQ to SQL 在向数据库发布更新后会抛出 ConcurrencyException。

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

【讨论】:

  • 谢谢。谢谢你。谢谢你。谢谢你。谢谢你。谢谢你。谢谢你。谢谢你。谢谢你。谢谢你。谢谢你。谢谢你。谢谢你。谢谢你。谢谢你。谢谢你。谢谢你。谢谢你。谢谢你。谢谢你。谢谢你。谢谢你。谢谢你。谢谢你。谢谢你。谢谢你。谢谢你。谢谢你。谢谢你。谢谢你。谢谢你。谢谢你。谢谢你。谢谢你。谢谢你。谢谢你。谢谢你。谢谢你。谢谢你。谢谢你。谢谢你。谢谢你。谢谢你。谢谢你。谢谢你。谢谢你。谢谢你。谢谢你。谢谢你。谢谢你。谢谢你。谢谢你。谢谢你。谢谢你。 thx.ty
  • 得再去一次谢谢谢谢谢谢!
  • 很好的调查,只是为了更正一点,Linq to SQL 可能会使用从服务器返回的 'count' 值,但没有使用 @@ROWCOUNT,因为“@@ROWCOUNT 函数即使在SET NOCOUNT 已开启。” see here
【解决方案2】:

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

【讨论】:

  • 我了解Linq to Sql在更新行时的乐观并发策略,但是测试表中的这些行中的任何一个都绝对不可能被修改。有趣的是,当我向表中添加 TIMESTAMP 列时,我没有收到任何 ConflictChangeExceptions。
【解决方案3】:

我在使用 SQL Server 2008 时遇到了同样的问题,连接选项 no count已经关闭

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

【讨论】:

    【解决方案4】:

    首先记录有关问题的详细信息、冲突的行和字段以及冲突的值。

    要实现这样的详细日志,请在此处查看我的解决方案:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-20
      • 1970-01-01
      • 1970-01-01
      • 2015-10-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多