Обновление нескольких отношений «многие ко многим» - PullRequest
4 голосов
/ 06 октября 2011

У меня есть две таблицы, автомобили и водители, которые соединены третьей таблицей, CarDrivers, в отношениях «многие ко многим».

Мой пользовательский интерфейс позволяет пользователю проверять любое количество драйверов, связанных с текущим автомобилем. Каждая проверка указывает, что строка должна быть введена в таблицу CarDrivers.

У меня вопрос: какой самый эффективный способ обновить эти строки, когда пользователь отправляет форму?

Мне нужно пройти и добавить строку в CarDrivers для каждого проверенного элемента, а также удалить по одному для каждого не проверенного элемента, оставив при этом те, которые не изменились.

Единственный способ, которым я вижу, - это просматривать каждую комбинацию, по одной, и добавлять те, которые еще не существуют, или удалять те, которые необходимо удалить. Есть ли более гладкий путь?

Я могу использовать Entity Frameworks 4, ADO.NET, прямые запросы SQL или хранимые процедуры.

Ответы [ 2 ]

4 голосов
/ 06 октября 2011

Это именно тот сценарий, который был изобретен для обработки синтаксиса MERGE, в частности, предложение WHEN NOT MATCHED BY SOURCE.

Вообще говоря, поместите значения текущего состояния в промежуточную таблицу, а затем используйте MERGE для обработки действий INSERT и DELETE за один удар.

Вот краткий набросок:

CREATE TABLE Cars (VIN INTEGER NOT NULL UNIQUE);

CREATE TABLE Drivers (driver_licence_number INTEGER NOT NULL UNIQUE);

CREATE TABLE CarDrivers 
(
 VIN INTEGER NOT NULL REFERENCES Cars (VIN), 
 driver_licence_number INTEGER NOT NULL 
    REFERENCES Drivers (driver_licence_number)
);

INSERT INTO Cars VALUES (1), (2), (3);
INSERT INTO Drivers VALUES (22), (55), (99);

INSERT INTO CarDrivers VALUES (1, 22), (1, 55);

CREATE TABLE CarDrivers_staging
(
 VIN INTEGER NOT NULL REFERENCES Cars (VIN), 
 driver_licence_number INTEGER NOT NULL 
    REFERENCES Drivers (driver_licence_number)
);

INSERT INTO CarDrivers_staging 
   VALUES (1, 55), -- remains
          (1, 99); -- insert
                   -- DELETE (1, 22)

MERGE INTO CarDrivers
   USING CarDrivers_staging S 
      ON S.VIN = CarDrivers.VIN
         AND S.driver_licence_number = CarDrivers.driver_licence_number 
WHEN NOT MATCHED THEN
   INSERT (VIN, driver_licence_number)
      VALUES (VIN, driver_licence_number)
WHEN NOT MATCHED BY SOURCE THEN
   DELETE;
2 голосов
/ 06 октября 2011

Я сомневаюсь, что это более эффективно, но, может быть, более «гладко», особенно если у вас нет большого количества данных.Когда пользователь отправляет форму, которая обновляет отношения автомобили-водители, почему бы сначала не удалить ВСЕ отношения в CarDrivers, связанные с ним, а затем вставить только те, которые они проверяли?В качестве альтернативы вы можете иметь ограничение uniq для обоих столбцов в CarDrivers, а затем просто беспокоиться о вставке и удалении, а не проверять существующие записи в вашем коде.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...