删除后对象立即重新插入数据库(DbLinq)

发布于 2024-08-19 16:28:13 字数 1695 浏览 4 评论 0原文

我有一个 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 列表的列表框。

我尝试在以下代码段运行之前和之后运行上面的删除代码:

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()

I have a MySql database, whose general structure looks like this:

Manufacturer <== ProbeDefinition <== ImagingSettings
  ElementSettings  ====^ ^==== ProbeInstance

I'm using InnoDB to allow foreign keys, and all foreign keys pointing to a ProbeDefinition have set ON DELETE CASCADE.

The issue I'm having is when I delete a ProbeDefinition in my code, it gets immediately reinserted. The cascading delete happens properly so other tables are cleared, but it seems that the LINQ to SQL may be sending an insert for no reason. Checking the ChangeSet property on the database shows 1 delete, and no inserts.

I'm using the following small bit of code to perform the delete:

database.ProbeDefinition.DeleteOnSubmit(probe);
database.SubmitChanges();

Logs in MySql show the following commands being executed when this is run:

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 */

What could cause this unnecessary INSERT? Note that deleting a Manufacturer in the exact same way deletes correctly, with the following log:

BEGIN 
use `wetscoprobes`; DELETE FROM wetscoprobes.manufacturer WHERE ID = 9 
COMMIT /* xid=2668 */ 

Edit: Upon further testing, it seems that this only happens after I've populated a ListBox with a list of ProbeDefinitions.

I tried running the above delete code before and after the following snippet had run:

var manufacturer = (Manufacturer)cbxManufacturer.SelectedItem;
var probes = manufacturer.ProbeDefinition;

foreach (var probe in probes)
{
    cbxProbeModel.Items.Add(probe);
}

The object gets deleted properly before said code has run, but anytime after this point, it performs an insert after the delete. Does it not like the fact that the object is referenced somewhere?

Here's the code I'm running to test deleting a definition from the intermediate window:

database.ProbeDefinition.DeleteOnSubmit(database.ProbeDefinition.Last())
database.SubmitChanges()

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

雨落星ぅ辰 2024-08-26 16:28:13

事实证明,当对象有多个引用时就会出现问题。通过逐步浏览 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,并在每个方法中重新连接到数据库。

Turns out there are issues when there are multiple references to your object. Stepping through the DbLinq source, I learned that after a DELETE is completed, it steps through all other "watched" objects, looking for references.

In this case, I have multiple references through the table database.ProbeDefinition as well as through the manufacturer reference, manufacturer.ProbeDefinition. This isn't an issue till I have accessed objects through both methods. Using Remove can delete the reference from manufacturer, using DeleteOnSubmit will delete the the object from the table. If I do one or the other, the other reference still exists, and thus the object is marked to be reinserted. I'm not sure if this is a bug in DbLinq that it doesn't delete other references, or expected behavior.

Either way, in my case, the solution is to either access the table using only a single method, and delete using that method, or to delete using both methods. For the sake of getting it working, I used the second method:

// Delete probe
this.manufacturer.ProbeDefinition.Remove(probe);
database.ProbeDefinition.DeleteOnSubmit(probe);
database.SubmitChanges();

EDIT: Upon further work on the project and similar issues, I have found the true underlying issue of my implementation. I have a long-lived DataContext, and with how caching works (to make SubmitChanges work), you can't do this. The real solution is to have a short-lived DataContext, and reconnect to the database in each method.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文