更新多个多对多关系

Jon*_*ood 4 sql sql-server ado.net entity-framework

我有两个表 Cars 和 Drivers,它们与第三个表 CarDrivers 以多对多关系连接。

我的 UI 允许用户检查与当前汽车相关联的任意数量的司机。每次检查都表明应在 CarDrivers 表中输入一行。

我的问题是:当用户提交表单时更新这些行的最有效方法是什么?

我需要检查并在 CarDrivers 中为每个已选中的项目添加一行,并为每个未选中的项目删除一个,同时保留那些未更改的项目。

我看到的唯一方法是遍历每个组合,一次一个,然后添加那些尚不存在的组合或删除那些需要删除的组合。有更巧妙的方法吗?

我可以使用实体框架 4、ADO.NET、直接 SQL 查询或存储过程。

one*_*hen 5

这正是MERGE发明语法要处理的场景,尤其是WHEN NOT MATCHED BY SOURCE子句。

广义上讲,将当前状态值放入一个临时表中,然后MERGE用于一次性处理INSERTDELETE操作。

这是一个简短的草图:

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;
Run Code Online (Sandbox Code Playgroud)