2012-03-08 3 views
1

У меня есть модель ниже.Удаление отношений «многие ко многим» в Entity Framework вызывает ошибку

enter image description here

Я пытаюсь удалить данную ProductType, связанный с ActivityType; Но когда я пытаюсь инициировать удаление с помощью моих общих методов, это не только удаление отношений, но и попытка удалить ProductType! с первичным ключом Zero в аргументе where, вызывающим erorr

«Заявление о сохранении, вставке или удалении повлияло на неожиданное количество строк (0). Объекты могут быть изменены или удалены с момента загрузки объектов. Записи ObjectStateManager. "

код для удаления ниже;

public void DeleteEntityAndSaveChanges<T, T1>(T entity, List<T1> subEntities) 
      where T : class 
      where T1 : class 
     { 
      Set<T>().Attach(entity); 
      DeleteEntitiesAndSaveChanges(subEntities); 
     } 

public void DeleteEntitiesAndSaveChanges<T>(List<T> entities) where T : class 
     { 
      foreach (var entity in entities) 
      { 
       Set<T>().Attach(entity); 
       Set<T>().Remove(entity); 
      } 

      SaveChanges(); 
     } 

Использование:

DbContext.DeleteEntityAndSaveChanges(request.ActivityType, request.ActivityType.ProductTypes); 

Это SQL, то будет генерируется:

exec sp_executesql N'delete [dbo].[ProductTypeActivityTypes] 
where (([ProductType_ProductTypeId] = @0) and ([ActivityType_EntityObjectId] = @1))',N'@0 bigint,@1 bigint',@0=1,@1=20 

Это виновный SQL, который не хотят разослал, но в настоящее время генерируемое EF:

Exec sp_executesql N'delete [DBO]. [ProductTypes] где (([ProductTypeId] = @ 0) и [TimeStamp] равно нулю)», N '@ 0 BIGINT', @ 0 = 1

любые идеи относительно того, как я могу заставить его только удалить отношения?

Cheers.

ответ

3

Когда вы вызываете Remove на DbSet, это означает удаление этого объекта из базы данных при вызове SaveChanges. Насколько я понимаю, вы действительно хотите удалить связь между двумя объектами. В общем, вы делаете это, удаляя одну сущность из свойства навигации коллекции другого объекта. Например:

product.Activities.Remove(activity); 

Но здесь есть морщина. В вашем примере кода вы вызываете Attach для присоединения обоих типов объектов к контексту. Calling Attach не будет устанавливать или восстанавливать какие-либо отношения между объектами. Это связано с тем, что для отношений «многие ко многим» в сущности нет FK, чтобы предоставлять информацию о том, как она связана с другими объектами. FK обрабатываются таблицей соединений, которая не отображается в сопоставлении EF со многими адресами.

Существует несколько подходов к решению этой проблемы. Во-первых, если это возможно и разумно для вашей архитектуры, вы можете позволить контексту EF отслеживать объекты с момента их запроса до момента, когда вы вызываете SaveChanges. Таким образом, EF будет отслеживать ваши отношения, включая отслеживание удалений.

Во-вторых, если сущности должны быть привязаны к новому контексту, вам нужно будет отслеживать отношения, чтобы их можно было восстановить. Есть несколько способов восстановить отношения. Один из способов - построить график связанных объектов перед вызовом Attach. Затем EF пересекает и присоединяет весь график, включая отношения, когда вызывается Attach.Например:

// Restore the graph 
product.Activities.Add(activity1); 
product.Activities.Add(activity2); 
context.Products.Attach(product); 

// Delete the relationship 
product.Activities.Remove(activity1); 
context.SaveChanges(); 

(я не использую общие методы, которые вы должны просто сделать код немного более четким Он должен работать так же, как с дженерик.).

Смежные вопросы