Question

J'utiliser Entity Framework 4 et j'ai parent - relation enfant avec "Cascade Supprimer" set. Donc j'attendre quand je retirer un enfant du parent que l'enfant est supprimé lorsque j'appelle SaveChanges ().

        cuRepository.Attach(_controlUnit);
        foreach (var recipe in recipes) {
            _controlUnit.Recipes.Remove(recipe);
            //repository.DeleteObject(recipe);
        }

Au lieu de cela je reçois une erreur:

  

System.InvalidOperationException Message = a eu lieu l'opération   a échoué: La relation ne pouvait pas être changé parce que l'un ou plusieurs des   les propriétés de clé étrangère est non annulable. Lorsqu'une modification est apportée à un   relation, la propriété de clé étrangère liée est réglée sur une valeur nulle.   Si la clé étrangère ne prend pas en charge les valeurs nulles, une nouvelle relation   doit être définie, la propriété clé étrangère doit être attribué une autre   La valeur non nulle, ou sans rapport avec l'objet doit être supprimé.

Lorsque je supprime explicitement les enfants (voir ligne commentée), tout va bien. Qu'est-ce que je manque?

Était-ce utile?

La solution

Vous ne supprimez pas l'objet avec l'instruction supprimer. vous essayez de modifier au lieu d'un dossier et de le rendre orphelin (en définissant la clé étrangère null). La base de données a une contrainte non nulle sur cette colonne et vous empêche de le faire.

Autres conseils

http :. //weblogs.asp.net/zeeshanhirani/archive/2010/07/23/removing-entity-from-a-related-collection.aspx explique exactement ce qui est arrivé à vous


En supposant que vous avez quelque chose de conception de classe comme ceci:

conception de classe exemple

Entity Framework génère les clés nécessaires colonnes étrangères et ajouter des contraintes de NOT NULL à eux parce que toutes les recettes seront toujours associés à exactement une unité de contrôle.

lors de l'exécution, vous aurez des objets similaires à la disposition suivante:

diagramme d'objets lors de l'exécution

Maintenant, votre code entre en jeu et a supprimé la relation entre les objets de recette et de leur unité de contrôle:

objets avec des relations supprimées

Essayer de sauver à ce moment, la base de données ne dispose pas d'un ID de mettre en unité de contrôle de la colonne de NOT NULL clé étrangère. L'état actuel de l'objet viole le diagramme de classes ci-dessus et ne peut pas être enregistré dans une mise en page de base de données qui a été générée en supposant que chaque recette est associée à une unité de contrôle. Ceci est la raison pour laquelle la base de données refuse d'enregistrer les modifications et vous voyez l'exception.

Cela explique aussi pourquoi il fonctionne lorsque vous supprimez la ligne suppression de l'entité. L'entité est supprimée de la base de données ainsi que ses relations, donc aucune contrainte ne viole donc pas d'exception

"Mais je mis ON DELETE CASCADE sur la relation ..."

Oui, mais qui est seulement déclenché sur la suppression de l'objet, non pas sur la suppression de la relation. Avec set ON DELETE CASCADE, cela devrait fonctionner:

controlUnitRepository.DeleteObject(_controlUnit);
// deletes the ControlUnit and all associated Recipe entities

Si vous voulez déclencher la suppression des entités de recettes sur la suppression de leur relation avec unité de contrôle, votre relation ne doit pas être une simple association, mais plutôt une composition:

diagramme de classe mises à jour avec la composition

EF ne supporte pas nativement, mais vous pouvez imiter le comportement en utilisant l'identification des relations. Une fois que l'entité est dans une relation d'identification à une entité mère et cette relation est supprimée, l'entité est également supprimé. Il semble que c'était votre intention dès le départ. Pour plus d'informations sur la relation d'identification, consultez mise en œuvre d'identifier les relations avec EF4 où j'ai mis en identifier les relations avec EF4 et ont lié à plus de matériel de lecture.

ajouter context.DeleteObject(recipe) dans la boucle

Si vous faites la relation entre l'enfant et le parent d'un identifiant l'un vous pouvez supprimer les entités enfant de la collection. Vous devez faire une clé composite clé de l'enfant contenant la clé identifiant primaire du parent. De cette façon, EF sait qu'il doit retirer l'enfant.

relation Identification dit essentiellement si le parent n'existe pas, l'enfant n'a pas de sens. Cela signifie EF sait qu'il est sûr de supprimer l'enfant lorsque la relation est supprimée.

Voir cette question Identification relation et l'insertion d'entités enfants provoque « Impossible d'insérer la valeur explicite pour la colonne d'identité dans le tableau » et celui-ci Est-il possible de retirer l'enfant de la collecte et résoudre les problèmes sur SaveChanges?

J'utilise cette extension afin de ne pas ajouter une méthode dans DAL juste pour supprimer une entité (code tiré de http://blogs.msdn.com/b/alexj/archive/2009/06/ 08 / pointe-24-how-to-get-the-ObjectContext-de-un-entity.aspx ):

public static void Delete<T>(this EntityCollection<T> collection, T entityToDelete) where T : EntityObject, IEntityWithRelationships
{
    RelationshipManager relationshipManager = entityToDelete.RelationshipManager;

    IRelatedEnd relatedEnd = relationshipManager.GetAllRelatedEnds().FirstOrDefault();
    if (relatedEnd == null)
    {
        throw new Exception("No relationships found for the entity to delete. Entity must have at least one relationship.");
    }

    var query = relatedEnd.CreateSourceQuery() as ObjectQuery;
    if (query == null)
    {
        throw new Exception("The entity to delete is detached. Entity must be attached to an ObjectContext.");
    }

    query.Context.DeleteObject(entityToDelete);
    collection.Remove(entityToDelete);
}

Je puis supprimer une entité comme Order.Products.Delete(prod).

Les contraintes d'utiliser l'extension sont les suivants:
- l'entité doit avoir des relations;
-. Entité doit être jointe à ObjectContext

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top