Объект повторно вставляется в базу данных сразу после удаления (DbLinq) - PullRequest
0 голосов
/ 28 января 2010

У меня есть база данных 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 */ 

Редактировать: После дальнейшего тестирования кажется, что это происходит только после того, как я заполнил 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()

1 Ответ

1 голос
/ 29 января 2010

Оказывается, есть проблемы, когда есть несколько ссылок на ваш объект. Проходя по источнику DbLinq, я узнал, что после завершения DELETE он проходит по всем остальным «наблюдаемым» объектам в поисках ссылок.

В этом случае у меня есть несколько ссылок через таблицу database.ProbeDefinition, а также через ссылку производителя manufacturer.ProbeDefinition. Это не проблема, пока я не получу доступ к объектам с помощью обоих методов. Используя Remove можно удалить ссылку от производителя, используя DeleteOnSubmit удалит объект из таблицы. Если я делаю одно или другое, другая ссылка все еще существует, и, таким образом, объект помечается для повторной вставки. Я не уверен, что это ошибка в DbLinq, которая не удаляет другие ссылки или ожидаемое поведение.

В любом случае, в моем случае решение состоит в том, чтобы либо получить доступ к таблице, используя только один метод, и удалить, используя этот метод, либо удалить, используя оба метода. Чтобы заставить его работать, я использовал второй метод:

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

РЕДАКТИРОВАТЬ: После дальнейшей работы над проектом и аналогичными проблемами, я нашел истинную основную проблему моей реализации. У меня есть долгоживущий DataContext, и с тем, как работает кэширование (чтобы заставить SubmitChanges работать), вы не можете сделать это. Решение real заключается в создании недолговечного DataContext и повторного подключения к базе данных в каждом методе.

...