Ответ 1
Ожидается, что ничего не произойдет.
То, что вы хотите изменить или добавить, - это связь между объектами Service
и ServiceItem
. Но вы не можете манипулировать отношениями, установив состояние объекта в Modified
. Это обновляет только скалярные и сложные свойства, но не обладает свойствами навигации (= отношения). (Например, настройка состояния объекта Service
на Modified
будет отмечена как Service.Title
и Service.Description
и т.д. Как измененная, и убедитесь, что эти свойства сохранены в базе данных, но это не заботится о содержимом of Service.ServiceItems
.)
Единственное исключение, в котором вы можете изменить отношения, установив состояние в Modified
, - это ассоциации внешних ключей. Это ассоциации, которые имеют свойства внешнего ключа, выставленные в вашей модели, и они могут встречаться только для ассоциаций "один ко многим" или "один к одному". Отношения "многие ко многим" всегда являются независимыми ассоциациями, что означает, что они никогда не могут иметь свойство внешнего ключа в сущности. (Поскольку FK находятся в таблице соединений, но таблица соединений не является сущностью и "скрыта" от ваших классов моделей.)
Существует способ прямого отношения к отношениям для ассоциации "многие-ко-многим", но для этого требуется перейти к ObjectContext
и его RelationshipManager
, который, на мой взгляд, довольно продвинутый и сложный.
Обычный и прямой способ добавления и удаления записей отношений в/из ассоциации "многие-ко-многим" - это просто добавление элементов и удаление элементов из коллекций, в то время как сущности привязаны к контексту. Механизм отслеживания изменений EF распознает сделанные вами изменения и сгенерирует соответствующие инструкции INSERT, UPDATE и DELETE при вызове SaveChanges
.
Точная процедура зависит от того, хотите ли вы сохранить Service
и/или ServiceItem
в качестве новых объектов или хотите только добавить отношения между существующими объектами. Вот несколько примеров:
-
Service
должен быть INSERTed, всеServiceItem
должны быть INSERTED, а отношения между сущностями также должны быть INSERTed в таблице соединений:using (var context = new MyContext()) { var service = new Service(); var serviceItem1 = new ServiceItem(); var serviceItem2 = new ServiceItem(); service.ServiceItems.Add(serviceItem1); service.ServiceItems.Add(serviceItem2); context.Services.Add(service); context.SaveChanges(); }
Добавление "root"
Service
графа объекта достаточно, потому что EF распознает, что все другие объекты в графе не привязаны к контексту и предполагают, что они должны быть INSERTed в базу данных. -
Service
уже существует и НЕ должен быть INSERTed, всеServiceItem
должны быть INSERTed, и отношения между сущностями также должны быть INSERTed в таблице соединений:using (var context = new MyContext()) { var service = new Service { ServiceID = 15 }; context.Services.Attach(service); var serviceItem1 = new ServiceItem(); var serviceItem2 = new ServiceItem(); service.ServiceItems.Add(serviceItem1); service.ServiceItems.Add(serviceItem2); context.SaveChanges(); }
EF распознает здесь (когда вызывается
SaveChanges
), чтоService
прикреплен, но другие объекты не являются. Нет INSERT дляService
, ноserviceItem1/2
будет INSERTed вместе с записями отношений. -
Service
уже существует и НЕ должен быть INSERTed, всеServiceItem
уже существуют и НЕ должны быть INSERTed, но отношения между объектами должны быть INSERTed в таблице соединений:using (var context = new MyContext()) { var service = new Service { ServiceID = 15 }; context.Services.Attach(service); var serviceItem1 = new ServiceItem { ServiceItemID = 23 }; context.ServiceItems.Attach(serviceItem1); var serviceItem2 = new ServiceItem { ServiceItemID = 37 }; context.ServiceItems.Attach(serviceItem2); service.ServiceItems.Add(serviceItem1); service.ServiceItems.Add(serviceItem2); context.SaveChanges(); }
-
Для полноты: как удалить отношения между существующими объектами?
using (var context = new MyContext()) { var service = context.Services .Include(s => s.ServiceItems) // load the existing Items .Single(s => s.ServiceID == 15); var serviceItem1 = service.ServiceItems .Single(s => s.ServiceItemID == 23); // query in memory, no DB query var serviceItem2 = service.ServiceItems .Single(s => s.ServiceItemID == 37); // query in memory, no DB query service.ServiceItems.Remove(serviceItem1); service.ServiceItems.Remove(serviceItem2); context.SaveChanges(); }
Две строки отношений в таблице соединений, которые связывают службу 15 с serviceItem 23 и 37, будут удалены.
Альтернативно вместо вызова Attach
вы можете загрузить существующие сущности из базы данных. Он также будет работать:
var service = context.Services.Single(s => s.ServiceID == 15);
И то же самое для существующих ServiceItem
s.