I have problem with deleting related rows in Entity Framework 4.1. I have tables with relations
Book 1<--->* BookFormats
I have set the on delete cascade:
ALTER TABLE [dbo].[BookFormats] WITH CHECK ADD CONSTRAINT [FK_BookFormats_Book]
FOREIGN KEY([BookID]) REFERENCES [dbo].[Book] ([BookID]) on delete cascade
The EDMX property
Then, I want to remove the all BokFormats
items related to my Book
object:
var originalBook = m.db.Book.First(x => x.BookID == bookId);
originalBook.BookFormats.Clear();
m.db.SaveChanges();
But, I get the error:
The operation failed: The relationship could not be changed because
one or more of the foreign-key properties is non-nullable. When a
change is made to a relationship, the related foreign-key property is
set to a null value. If the foreign-key does not support null values,
a new relationship must be defined, the foreign-key property must be
assigned another non-null value, or the unrelated object must be
deleted.
I ran out of ideas on how to delete these objects. Any ideas?
Cascade deletions concept is as follows:
When you delete Book
from the DB all related BookFormats
will be deleted for you by SQL Server (please note that it doesn't matter how deletion of Book
will be initiated via EF or raw SQL). Thus it has nothing to do with your task: "I want to delete all BookFormats
related to my Book
". To accomplish it you need something like this:
foreach(var m in m.db.BookFormats.Where(f=>f.BookID == bookID))
{
m.db.BookFormats.Remove(m);
}
m.db.SaveChanges();
You can use RemoveRange :
m.db.BookFormats.RemoveRange(originalBook.BookFormats);
m.db.SaveChanges();
But this is for EF 6.0
You are not deleting the BookFormats
from the database, but you are removing the relationship, thus orpahning your BookFormats
and setting the BookID
column to NULL. The delete cascade you have put on the database says When I delete the
Book, then delete all of the
BookFormatsthat have a
BookIDequal to mine.
You are not deleting the book you are deleting the formats from the Book
.
Instead of originalBook.BookFormats.Clear()
you should have something like this...
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();
It should be something along those lines. I don't have it right in front of me to remember how EF constructs the delete method in the EDMX.
I've tested it in EF 6.1.3 and this should work fine:
var originalBook = m.db.Book.First(x => x.BookID == bookId);
originalBook.BookFormats.Clear();
db.Books.Remove(originalBook);
m.db.SaveChanges();
I use EF6 and this works.
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();