我有一个MySql数据库,其总体结构如下:
Manufacturer <== ProbeDefinition <== ImagingSettings
ElementSettings ====^ ^==== ProbeInstance
我正在使用InnoDB来允许外键,而指向ProbeDefinition
的所有外键都设置了ON DELETE CASCADE
。
我遇到的问题是当我在代码中删除ProbeDefinition
时,会立即重新插入。级联删除正确发生,因此其他表被清除,但似乎LINQ to SQL可能无缘无故地发送插入。检查数据库上的ChangeSet属性显示1删除,没有插入。
我正在使用以下一小段代码来执行删除:
database.ProbeDefinition.DeleteOnSubmit(probe);
database.SubmitChanges();
登录MySql显示运行此命令时正在执行的以下命令:
BEGIN
use `wetscoprobes`; DELETE FROM wetscoprobes.probedefinition WHERE ID = 10
use `wetscoprobes`; INSERT INTO wetscoprobes.probedefinition (CenterFrequency, Elements, ID, IsPhased, ManufacturerID, Name, Pitch, Radius, ReverseElements) VALUES (9500000, 128, 10, 1, 6, 'Super Probe 2', 300, 0, 1)
COMMIT /* xid=2424 */
什么可能导致这种不必要的INSERT
?请注意,以完全相同的方式删除Manufacturer
会正确删除,并使用以下日志:
BEGIN
use `wetscoprobes`; DELETE FROM wetscoprobes.manufacturer WHERE ID = 9
COMMIT /* xid=2668 */
编辑:经过进一步测试,似乎只有在我填充了列表ProbeDefinition
s的ListBox后才会发生这种情况。
我尝试在以下代码段运行之前和之后运行上面的删除代码:
var manufacturer = (Manufacturer)cbxManufacturer.SelectedItem;
var probes = manufacturer.ProbeDefinition;
foreach (var probe in probes)
{
cbxProbeModel.Items.Add(probe);
}
在所述代码运行之前,对象被正确删除,但在此之后的任何时间,它都会在删除后执行插入。它不喜欢在某处引用对象的事实吗?
这是我正在运行的代码,用于测试从中间窗口删除定义:
database.ProbeDefinition.DeleteOnSubmit(database.ProbeDefinition.Last())
database.SubmitChanges()
答案 0 :(得分:1)
当您的对象有多个引用时,会出现问题。通过DbLinq源代码,我了解到在DELETE
完成后,它会逐步浏览所有其他“监视”对象,寻找参考。
在这种情况下,我通过表database.ProbeDefinition
以及制造商参考manufacturer.ProbeDefinition
进行了多次引用。在我通过两种方法访问对象之前,这不是问题。使用Remove
可以删除制造商的引用,使用DeleteOnSubmit
将从表中删除该对象。如果我执行其中一个,则另一个引用仍然存在,因此该对象被标记为重新插入。我不确定这是否是DbLinq中的一个错误,它不会删除其他引用或预期的行为。
无论哪种方式,在我的情况下,解决方案是仅使用单个方法访问表,使用该方法删除,或使用两种方法删除。为了让它正常工作,我使用了第二种方法:
// Delete probe
this.manufacturer.ProbeDefinition.Remove(probe);
database.ProbeDefinition.DeleteOnSubmit(probe);
database.SubmitChanges();
编辑:在进一步研究项目和类似问题后,我发现了我的实施的真正根本问题。我有一个长期存在的DataContext,以及缓存如何工作(使SubmitChanges工作),你不能这样做。 真正的解决方案是使用短暂的DataContext,并在每种方法中重新连接到数据库。