Удаление отношения многие ко многим в Entity Framework выдает ошибку - PullRequest
0 голосов
/ 08 марта 2012

У меня есть модель ниже.

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

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

Приветствие.

1 Ответ

3 голосов
/ 08 марта 2012

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

product.Activities.Remove(activity);

Но здесь есть морщина.В вашем примере кода вы вызываете Attach, чтобы присоединить оба типа сущностей к контексту.Вызов 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();

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

...