【问题标题】:C# LINQ-TO-SQL: datacontext.ChangeConflicts not showing all conflictsC# LINQ-TO-SQL:datacontext.ChangeConflicts 未显示所有冲突
【发布时间】:2011-08-21 00:19:02
【问题描述】:

我在使用 linq-to-sql 并尝试解决冲突时遇到了问题。问题是有时没有检测到冲突。请查看以下代码示例:

// Setup the object to re-produce the problem
//
// MyObject has properties: id, my_string, my_int and version (timestamp) to enable
// conflicts detection
var context = new MyDataContext();
var obj = new MyObject();
obj.id = "1";
obj.my_string = "value";
obj.my_int    = 0;
context.MyTable.InsertOnSubmit(obj);
context.SubmitChanges();
context.dispose();

// Get 2 data contexts         
var context1 = new MyDataContext();
var context2 = new MyDataContext();

// Get 2 instances of obj - 1 from each context
var obj1= context1.MyTable.SingleOrDefault(o => o.id == "1");
var obj2= context2.MyTable.SingleOrDefault(o => o.id == "1");

// Change the values of obj1 and update it to the database
obj1.my_string= "value1";
obj1.my_int= 0;
context1.SubmitChanges();
context1.Dispose();

// Update the changes in obj2
obj2.my_string= "value2";
obj2.my_int= 1;

// Now the database contains:
//   id:        "1"
//   my_string: "value1"
//   my_int:    0

// obj2 contains:
//   id:        "1"
//   my_string: "value2"
//   my_int:    1

try
{
  context2.SubmitChanges();
}
catch(ChangeConflictException ex)
{
  LogInfo("Conflicting members:");
  context2.ChangeConflicts[0].MemberConflicts.ToList().ForEach(
                mcc=>LogInfo("Property '{0}': Database value: {1}, Current Value:{2}", mcc.Member.Name, mcc.DatabaseValue, mcc.CurrentValue)
                );
}
context2.Dispose();

在捕获中,我希望看到 3 个成员冲突:my_string、my_int 和版本,但我只看到 2 个成员冲突:my_string 和版本。 my_int 未被检测为冲突。

如果我在创建对象时将 my_int 设置为与我分配给 obj2 的值不同的值,则会检测到冲突。

我发现了一些共性:当原始对象的某个属性(任何属性)的值等于obj1的值时,不会检测到该属性的冲突。

我想知道如何解决这个问题,以便成功检测到冲突

【问题讨论】:

  • 这不是 my_int 的冲突 - 当从数据库加载 obj2 时,旧值是 0。数据库中的当前值为0
  • 谢谢达米安,确实是这样。

标签: c# linq-to-sql conflict


【解决方案1】:

我找到了问题的根本原因。我没有与“my_int”属性发生冲突的原因是它与 context2“知道”的数据库值不冲突。我来解释一下:

我认为冲突被定义为当保存的对象的值不等于数据库中的值时不是!!!!

冲突定义为当数据库中的当前值不等于上下文熟悉的原始值时。原始值是执行选择查询时数据库中的值。

检查我的问题中的示例,当 context2 从数据库中选择数据来创建 obj2 时,properties 值为:my_string: "value", my_int:0。这些是原始值。

当我尝试保存数据时,LINQ-TO-SQL 将原始值与数据库值进行比较。此时的数据库值(保存obj1后):my_string: "value1", my_int:0

结果,我在 my_string (original: "value", database:"value1") 中遇到了冲突,但在 my_int(original: 0, database: 0) 中没有。

发现这一点帮助我理解了为什么没有冲突,但它仍然没有帮助我解决问题,因为错误的值没有保存到数据库中,因为我只分析了 ObjectChangeConflict 中存在的 MemberChangeConflicts,如果我正在检查的属性不存在,检查逻辑被跳过。

解决方案是同时分析修改后的可枚举成员,这些成员可以访问所有已修改的属性,并且对于每个属性,我可以获得原始值和新值。

要获取修改后的成员,需要执行名为 GetModifiedMembers 的方法。该方法在对象数据类型的表中,执行如下:

 var mmc = context.MyTable.GetModifiedMembers(myobject);

将冲突和修改后的成员结合起来,我可以全面了解导致冲突的对象发生了什么并正确处理它。

感谢 Damien_The_Unbeliever 在他的评论中给出提示。

【讨论】:

    猜你喜欢
    • 2020-12-28
    • 1970-01-01
    • 2023-01-10
    • 1970-01-01
    • 2012-02-20
    • 2018-02-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多