web-dev-qa-db-fra.com

Entity Framework sur la suppression en cascade

Je ne parviens pas à supprimer les lignes associées dans Entity Framework 4.1. J'ai des tables avec des relations

Livre 1 <---> * BookFormats

J'ai mis la cascade sur supprimer:

ALTER TABLE [dbo].[BookFormats]  WITH CHECK ADD  CONSTRAINT [FK_BookFormats_Book] 
FOREIGN KEY([BookID]) REFERENCES [dbo].[Book] ([BookID]) on delete cascade

La propriété EDMX

enter image description here

Ensuite, je souhaite supprimer tous les éléments BokFormats liés à mon objet Book:

 var originalBook = m.db.Book.First(x => x.BookID == bookId);
 originalBook.BookFormats.Clear();
 m.db.SaveChanges();

Mais j'ai l'erreur:

L'opération a échoué: la relation n'a pas pu être modifiée car une ou plusieurs des propriétés de clé étrangère ne sont pas nullables. Lorsqu'un une modification est apportée à une relation, la propriété de clé étrangère associée est mis à une valeur nulle. Si la clé étrangère ne supporte pas les valeurs NULL, une nouvelle relation doit être définie, la propriété de clé étrangère doit être attribué une autre valeur non nulle, ou l'objet non lié doit être supprimé.

J'ai manqué d'idées sur la façon de supprimer ces objets. Des idées?

13
Tony

Le concept de suppression en cascade est le suivant:

Lorsque vous supprimez Book de la base de données, tous les BookFormats liés seront supprimés pour vous par SQL Server (veuillez noter que la suppression de Book n'a pas d'importance, elle sera lancée via EF ou SQL brut). Cela n'a donc rien à voir avec votre tâche: "Je veux supprimer tous les BookFormats liés à mon Book". Pour ce faire, vous avez besoin de quelque chose comme ceci:

foreach(var m in m.db.BookFormats.Where(f=>f.BookID == bookID))
{
    m.db.BookFormats.Remove(m);
}
m.db.SaveChanges();
10
Vitaliy Kalinin

Vous pouvez utiliser RemoveRange:

m.db.BookFormats.RemoveRange(originalBook.BookFormats);
m.db.SaveChanges();

Mais ceci est pour EF 6.0

17
Saykor

Vous ne supprimez pas la BookFormats de la base de données, mais vous supprimez la relation. Vous définissez ainsi votre BookFormats et définissez la colonne BookID surNULL. La cascade de suppression que vous avez mise dans la base de données indique When I delete theBook, then delete all of theBookFormatsthat have aBookIDequal to mine. Vous ne supprimez pas le livre que vous supprimez des formats de la Book.

Au lieu de originalBook.BookFormats.Clear(), vous devriez avoir quelque chose comme ça ...

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();

Ce devrait être quelque chose dans ce sens. Je n'ai pas le droit de me rappeler comment EF construit la méthode de suppression dans EDMX.

4
bdparrish

Je l'ai testé dans EF 6.1.3 et cela devrait fonctionner correctement:

 var originalBook = m.db.Book.First(x => x.BookID == bookId);
 originalBook.BookFormats.Clear();
 db.Books.Remove(originalBook);
 m.db.SaveChanges();
0
gbdavid

J'utilise EF6 et cela fonctionne.

        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();
0
prespic