为什么抛出第二个数据库冲突异常?

时间:2009-12-15 21:26:03

标签: c# .net linq-to-sql concurrency

我有一些linq2sql的东西可以更新一些行。 然后,当我提交时,我这样做:

try
{
    database.SubmitChanges();
}
catch (ChangeConflictException)
{
    database.ChangeConflicts.ResolveAll(RefreshMode.KeepChanges);
    database.SubmitChanges();
}

现在第二次提交(catch中的那个)再次抛出一个ChangeConflictException

怎么可能?如果有可能的话。如何进行查询? (我不能再试一次/抓住那个?我什么时候停止?)

我只希望将更改后的值放入数据库中。

编辑: 让我重新解释一下这个问题的意图:当我说'ResolveALL(keepchanges)'时,我会认为我说:“我不在乎......只是使用我的价值观”。相反,它再次抛出相同的异常。

我对此行为感到惊讶,因为MSDN上的示例没有第二次尝试捕获第二个SubmitChanges

那么可以抛出这些异常多少次(有多少次列?),我可以以某种方式完全避免它们(在说ResolveAll之后)?

编辑: 在我开始赏金前的最后一次编辑:

我按照其中一位评论者的建议将其变成了一个整洁的循环。但是我重试多少次并不重要。它开始抛出异常的那一刻,它永远不会没有例外!所以无论是第一次工作,还是根本不工作。

现在我的linq更新中有大约20或50行需要更新(我使用批处理来加快速度)。 每个解决方案只解决1列离子1行中的一个问题吗?或者它是否足够聪明以解决它遇到的一切?

回顾一下:我刚改变的值(只有1或2列)是需要进入数据库的值,无论如何。我怎么能用linq做这个(或者我真的应该为此打开一个SqlConnection?(如果是这样,为什么Linq首先?)

我的代码到现在为止:

 int retry;
 for (retry = 0; retry < 10; retry++)
 {
      try
      {
           database.SubmitChanges();
           //submit succeeded... break loop
           break;
      }
      catch (ChangeConflictException)
      {
           database.ChangeConflicts.ResolveAll(RefreshMode.KeepChanges);

           if (retry > 0)
           {
                Thread.Sleep(retry * 10);  //introduce some wait, to see if this helps
           }
      }
编辑:发现它!

由于在接受的答案中链接到博客,我现在循环遍历所有冲突并记录它们以查看导致此问题的原因。

我很高兴我做到了,因为事实证明其中一个数据库字段包含一个在某些条件下更新其他内容的触发器。因此,每当触发器再次触发时,我可以尽可能多地解决,导致下一次冲突。

这个触发器显然我没有注意到,因为我的数据库管理员把它放在那里跟踪某事或其他。触发器可以是一个很好的工具,但是如果你不了解它们就会引起严重的麻烦!

2 个答案:

答案 0 :(得分:2)

当您调用SubmitChanges()时,可能无法解决所有冲突(因此无法解决所有冲突),因为默认行为是在到达第一个时停止。

尝试更改

database.SubmitChanges();

database.SubmitChanges(ConflictMode.ContinueOnConflict);

有关详细信息,请参阅http://arun-ts.blogspot.com/2009/08/linq-to-sql-concurrency-conflicts.html。他还在ResolveAll()的代码示例中嵌套了两个级别的try / catch,因此第二次尝试SubmitChanges()时,他能够在退出之前记录任何异常。这似乎是一个合理的模型。

答案 1 :(得分:0)

如果您需要继续重试,那么代码的明显重新排序是:

bool success = false;
while (!success)
{
  try
  {
    database.SubmitChanges();
    success = true;
  }
  catch (ChangeConflictException)
  {
    database.ChangeConflicts.ResolveAll(RefreshMode.KeepChanges);
  }
}

我对数据库知之甚少,所以我会远离理论上你的实际问题,但也许这会解决它:/