Entity Framework при удалении каскада
У меня проблема с удалением связанных строк в Entity Framework 4.1. У меня есть таблицы с отношениями
Книга 1 < --- > * BookFormats
Я установил каскад on delete:
ALTER TABLE [dbo].[BookFormats] WITH CHECK ADD CONSTRAINT [FK_BookFormats_Book]
FOREIGN KEY([BookID]) REFERENCES [dbo].[Book] ([BookID]) on delete cascade
Свойство EDMX
![enter image description here]()
Затем я хочу удалить все элементы BokFormats
, связанные с моим объектом Book
:
var originalBook = m.db.Book.First(x => x.BookID == bookId);
originalBook.BookFormats.Clear();
m.db.SaveChanges();
Но я получаю сообщение об ошибке:
Не удалось выполнить операцию: отношения не могут быть изменены, поскольку одно или несколько свойств внешнего ключа не имеют значения NULL. Когда изменение производится в отношении, связанное с ним свойство внешнего ключа установить на нулевое значение. Если внешний ключ не поддерживает нулевые значения, необходимо определить новое отношение, свойство внешнего ключа должно быть назначено другое ненулевое значение, или не связанный с ним объект должен быть удален.
У меня кончились идеи о том, как удалить эти объекты. Любые идеи?
Ответы
Ответ 1
Концепция делегирования каскадов такова:
Когда вы удаляете Book
из БД, все связанные с ним BookFormats
будут удалены для вас SQL Server (обратите внимание, что не имеет значения, как будет инициировано удаление Book
через EF или raw SQL). Таким образом, это не имеет ничего общего с вашей задачей: "Я хочу удалить все BookFormats
, связанные с моим Book
". Для этого вам нужно что-то вроде этого:
foreach(var m in m.db.BookFormats.Where(f=>f.BookID == bookID))
{
m.db.BookFormats.Remove(m);
}
m.db.SaveChanges();
Ответ 2
Вы можете использовать RemoveRange:
m.db.BookFormats.RemoveRange(originalBook.BookFormats);
m.db.SaveChanges();
Но это для EF 6.0
Ответ 3
Вы не удаляете BookFormats
из базы данных, но вы удаляете взаимосвязь, таким образом, поддерживая свой BookFormats
и устанавливая столбец BookID
равным NULL. Каскад удаления, который вы положили в базу данных, говорит When I delete the
Book , then delete all of the
BookFormats that have a
BookID equal to mine.
Вы не удаляете книгу, которую вы удаляете из форматов из Book
.
Вместо originalBook.BookFormats.Clear()
у вас должно получиться что-то вроде этого...
List<int> idsToDelete = new List<int>();
foreach (BookFormat bf in originalBook.BookFormats)
{
idsToDelete.Add(bf.ID);
}
foreach (int id in idsToDelete)
{
BookFormat format = m.db.BookFormat.FirstOrDefault(x => x.ID == id);
if (format != null)
{
m.db.DeleteBookFormat(format);
}
}
m.db.SaveChanges();
Это должно быть что-то в этом роде. Я не имею права передо мной помнить, как EF создает метод удаления в EDMX.
Ответ 4
Я использую EF6, и это работает.
var itemBinding = db.ItemBinding.Where(x => x.BindingToId == id) ;
foreach (var ib in itemBinding)
{
db.Item.Remove(ib.Item);
db.ItemBinding.Remove(ib);
}
db.SaveChanges();
Ответ 5
Я тестировал его в EF 6.1.3, и это должно работать нормально:
var originalBook = m.db.Book.First(x => x.BookID == bookId);
originalBook.BookFormats.Clear();
db.Books.Remove(originalBook);
m.db.SaveChanges();