Объект повторно вставляется в базу данных сразу после удаления (DbLinq)
-
23-09-2019 - |
Вопрос
У меня есть база данных MySQL, общая структура которой выглядит следующим образом:
Manufacturer <== ProbeDefinition <== ImagingSettings
ElementSettings ====^ ^==== ProbeInstance
Я использую InnoDB для разрешения внешних ключей, и все внешние ключи, указывающие на ProbeDefinition
установили ON DELETE CASCADE
.
Проблема, с которой я сталкиваюсь, заключается в том, что когда я удаляю ProbeDefinition
в моем коде он немедленно вставляется повторно.Каскадное удаление происходит должным образом, поэтому другие таблицы очищаются, но, похоже, LINQ to SQL может отправлять insert без причины.Проверка свойства набора изменений в базе данных показывает 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 */
Редактировать: При дальнейшем тестировании кажется, что это происходит только после того, как я заполнил ListBox списком ProbeDefinition
s.
Я попытался запустить приведенный выше код удаления до и после запуска следующего фрагмента:
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()
Решение
Оказывается, возникают проблемы, когда существует несколько ссылок на ваш объект.Просматривая исходный код 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 и повторно подключаться к базе данных в каждом методе.