好的,您认为自己是真正的调试器吗?试试这个:
我有一个Linq2Sql项目突然间我们偶然发现,看似随机,我们得到同一行的双重插入。
我已将DataContext
子类化并覆盖SubmitChanges
。在那里,我在调用GetChangeSet()
之前和之后都调用了base.SubmitChanges()
,并使用文本文件记录器来记录Inserts
集合中的对象。另外,我会长时间插入对插入对象的引用,以记录其自动编号ID。
当双重插入发生时,我在数据库中看到,每个都插入MyTableA
和MyTableB
而不是每行插入一行。 SQL事件探查器显示四个插入语句,一个接一个地快速连续:
insert into MyTableA(...
insert into MyTableB(...
insert into MyTableA(...
insert into MyTableB(...
我签入了调试日志,Inserts
集合中只有两个对象:一个 MyClassA
和一个 { {1}}。调用MyClassB
后,更改集为空(应该是)。并且自动编号ID显示新插入行的更大值。
另一条有用的信息:在调试模式中单步执行时,从不发生错误;只有当你没有断点运行时。这让我怀疑它与执行速度有关。
我们一直使用相同的base.SubmitChanges()
子类超过一年,我们之前从未见过这种行为。它只发生在DataContext
和MyClassA
。
总结:
编辑 - 新信息:
在我的MyClassB
子类中,我有以下代码:
DataContext
try {
base.SubmitChanges(ConflictMode.ContinueOnConflict);
} catch (ChangeConflictException) {
// Automerge database values for members that client has not modified.
foreach (ObjectChangeConflict occ in ChangeConflicts) {
occ.Resolve(RefreshMode.KeepChanges);
}
}
// Submit succeeds on second try.
base.SubmitChanges(ConflictMode.FailOnFirstConflict);
和MyTableA
都有一个强制性外键MyTableB
引用OtherTableID
。在更新公共父表OtherTable
期间发生ChangeConflictException
时会发生双重插入。
我们现在有了气味......
答案 0 :(得分:0)
当我遇到这样的问题之前,通常会遇到多个线程同时执行相同的代码。
您是否尝试过使用 lock {} 命令确保插件只被单个线程使用? MSDN Lock
答案 1 :(得分:0)
在Linq2Sql中看起来像是 BUG !这是一个可重复的实验:
using (var db1 = new MyDataContext()) {
var obj1 = db1.MyObjects.Single(x => x.ID == 1);
obj1.Field1 = 123;
obj1.RelatedThingies.Add(new RelatedThingy {
Field1 = 456,
Field2 = "def",
});
using (var db2 = new MyDataContext()) {
var obj2 = db2.MyObjects.Single(x => x.ID == 1);
obj2.Field2 = "abc";
db2.SubmitChanges();
}
try {
db1.SubmitChanges(ConflictMode.ContinueOnConflict);
} catch (ChangeConflictException) {
foreach (ObjectChangeConflict occ in ChangeConflicts) {
occ.Resolve(RefreshMode.KeepChanges);
}
}
base.SubmitChanges(ConflictMode.FailOnFirstConflict);
}
结果:ID = 1的MyObject
记录更新,Field1值为123,Field2值为“abc”。还有两个新的,相同的记录插入到RelatedThingy,MyObjectID = 1,Field1 = 456,Field2 =“def”。
解释那个!
更新:在Microsoft Connect上记录此信息后,MS的优秀人员要求我整理一个突出显示该错误的小型演示项目。你不知道吗 - 我无法重现它。它似乎与我的项目的一些奇怪的特质有关。没有时间进一步调查,无论如何我找到了一个解决方法......
答案 2 :(得分:0)
FWIW,我们最近在SubmitChanges
的重试逻辑中发现了这个问题。我们正在做InsertAllOnSubmit
。发生ChangeConflictException
时,我们会在每个Resolve(RefreshMode.KeepChanges,true)
上使用ObjectChangeConflict
重试。
我们以不同的方式重新编写工作(重试逻辑以重新执行整个事务),这似乎解决了问题。