LINQ中的数据冲突

使用SubmitChanges()进行更改时,LINQ有时会因ChangeConflictExceptionexception而导致错误消息Row not found or changed ,而没有任何指示冲突的行或具有冲突的更改的字段,当另一个用户具有冲突时更改了该行中的一些数据。

有没有办法确定哪一行有冲突以及它们出现在哪些字段中,还有一种方法可以让LINQ忽略该问题并简单地提交数据吗?

此外,是否有人知道当行中的任何数据发生更改时,或者仅在LINQ尝试更改的字段中更改了数据时是否发生此exception?

这是一种查看冲突位置的方法(这是一个MSDN示例,因此您需要进行大量自定义):

 try { db.SubmitChanges(ConflictMode.ContinueOnConflict); } catch (ChangeConflictException e) { Console.WriteLine("Optimistic concurrency error."); Console.WriteLine(e.Message); Console.ReadLine(); foreach (ObjectChangeConflict occ in db.ChangeConflicts) { MetaTable metatable = db.Mapping.GetTable(occ.Object.GetType()); Customer entityInConflict = (Customer)occ.Object; Console.WriteLine("Table name: {0}", metatable.TableName); Console.Write("Customer ID: "); Console.WriteLine(entityInConflict.CustomerID); foreach (MemberChangeConflict mcc in occ.MemberConflicts) { object currVal = mcc.CurrentValue; object origVal = mcc.OriginalValue; object databaseVal = mcc.DatabaseValue; MemberInfo mi = mcc.Member; Console.WriteLine("Member: {0}", mi.Name); Console.WriteLine("current value: {0}", currVal); Console.WriteLine("original value: {0}", origVal); Console.WriteLine("database value: {0}", databaseVal); } } } 

无论如何要使它忽略问题并提交:

 db.SubmitChanges(ConflictMode.ContinueOnConflict); 

这些(您可以在您的datacontext的部分类中添加它们可能有助于您了解其工作原理:

 public void SubmitKeepChanges() { try { this.SubmitChanges(ConflictMode.ContinueOnConflict); } catch (ChangeConflictException e) { foreach (ObjectChangeConflict occ in this.ChangeConflicts) { //Keep current values that have changed, //updates other values with database values occ.Resolve(RefreshMode.KeepChanges); } } } public void SubmitOverwrite() { try { this.SubmitChanges(ConflictMode.ContinueOnConflict); } catch (ChangeConflictException e) { foreach (ObjectChangeConflict occ in this.ChangeConflicts) { // All database values overwrite current values with //values from database occ.Resolve(RefreshMode.OverwriteCurrentValues); } } } public void SubmitKeepCurrent() { try { this.SubmitChanges(ConflictMode.ContinueOnConflict); } catch (ChangeConflictException e) { foreach (ObjectChangeConflict occ in this.ChangeConflicts) { //Swap the original values with the values retrieved from the database. No current value is modified occ.Resolve(RefreshMode.KeepCurrentValues); } } } 

我在与错误消息描述的内容完全无关的情况下得到了这个错误。

我所做的是通过一个DataContext加载LINQ对象,然后通过不同的DataContext尝试SubmitChanges()为对象 – 给出了完全相同的错误。

我必须做的是调用DataContext.Table.Attach(myOldObject),然后调用SubmitChanges(),就像一个魅力。

值得一看,特别是如果你认为根本不应该有任何冲突。

当O / R-Designer中的列或类型与SQL数据库中的列不匹配时,有时也会出现错误“未找到或未更改行”,尤其是当一列在SQL中为NULL但在O /中不可为空时R-设计师。

因此,请检查O / R-Designer中的表映射是否与SQL数据库匹配!

感谢@vzczc。 我发现你提供的示例非常有用,但我需要在解决后再次调用SubmitChanges。 以下是我修改过的方法 – 希望它有所帮助。

  ///  /// Submits changes and, if there are any conflicts, the database changes are auto-merged for /// members that client has not modified (client wins, but database changes are preserved if possible) ///  public void SubmitKeepChanges() { this.Submit(RefreshMode.KeepChanges); } ///  /// Submits changes and, if there are any conflicts, simply overwrites what is in the database (client wins). ///  public void SubmitOverwriteDatabase() { this.Submit(RefreshMode.KeepCurrentValues); } ///  /// Submits changes and, if there are any conflicts, all database values overwrite /// current values (client loses). ///  public void SubmitUseDatabase() { this.Submit(RefreshMode.OverwriteCurrentValues); } ///  /// Submits the changes using the specified refresh mode. ///  /// The refresh mode. private void Submit(RefreshMode refreshMode) { bool moreToSubmit = true; do { try { this.SubmitChanges(ConflictMode.ContinueOnConflict); moreToSubmit = false; } catch (ChangeConflictException) { foreach (ObjectChangeConflict occ in this.ChangeConflicts) { occ.Resolve(refreshMode); } } } while (moreToSubmit); } 

“还有一种方法可以让LINQ忽略这个问题并简单地提交数据吗?”

您可以将实体上的“更新检查”属性设置为“从不”以停止用于乐观并发检查的字段。

您还可以使用:

 db.SubmitChanges(ConflictMode.ContinueOnConflict)