Domanda

I utilizzare Entity Framework 4 e devo genitore - bambino con relazione "Cascade Delete" impostato. Quindi mi aspetterei quando rimuovo un figlio dal genitore che il bambino viene eliminato Quando chiamo SaveChanges ().

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

Invece ottengo un errore:

  

System.InvalidOperationException verificato Message = L'operazione   non riuscita: Il rapporto non potrebbe essere cambiato perché uno o più dei   le proprietà di chiave esterna è non annullabile. Quando viene apportata una modifica a un   rapporto, la proprietà di chiave correlate è impostata su un valore nullo.   Se il-chiave esterna non supporta i valori nulli, un nuovo rapporto   deve essere definito, la proprietà di chiave esterna deve essere assegnato un altro   valore non nullo, o l'oggetto non correlato deve essere eliminato.

Quando si elimina in modo esplicito i bambini (vedi linea commentato), tutto va bene. Che cosa mi manca?

È stato utile?

Soluzione

Non si elimina l'oggetto con la dichiarazione di rimozione. Invece si sta tentando di modificare un record e renderlo orfano (impostando la chiave esterna a null). Il database ha un vincolo non nullo su quella colonna e vi impedisce di farlo.

Altri suggerimenti

http :. //weblogs.asp.net/zeeshanhirani/archive/2010/07/23/removing-entity-from-a-related-collection.aspx spiega esattamente cosa ti è successo


Supponendo di avere un qualcosa di design di classe in questo modo:

loading="lazy"

Entity Framework genererà le colonne chiave esterna richiesti e aggiungere vincoli NOT NULL a loro perché tutte le ricette saranno sempre associati con esattamente un Unità di controllo.

Quindi, in fase di esecuzione si dovrà oggetti simili al seguente schema:

Schema oggetto in fase di esecuzione

Ora il codice entra in gioco e cancellato la relazione tra gli oggetti ricetta e la loro Unità di controllo:

oggetti con relazioni eliminati

Cercando di salvare in questo momento, il database non ha un ID Unità di controllo per mettere in colonna NOT NULL chiave esterna. Lo stato oggetto corrente viola diagramma delle classi sopra e non possono essere salvati in un formato database che è stato generato in base al presupposto che ogni ricetta è associato a un'Unità di controllo. Questo è il motivo per cui il database si rifiuta di salvare le modifiche e si vede l'eccezione.

Questo spiega anche perché funziona quando si rimuove il commento dalla riga eliminando l'entità:. L'entità viene rimossa dal database insieme al suo rapporto, in modo vincoli sono violati, pertanto, non fa eccezione

"Ma ho impostato ON DELETE CASCADE sul rapporto ..."

Sì, ma che viene attivato solo sulla eliminazione dell'oggetto, non sulla cancellazione del rapporto. Con set ON DELETE CASCADE, questo dovrebbe funzionare:

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

Se si desidera attivare la cancellazione delle entità ricetta su cancellazione del loro rapporto con Unità di controllo, il vostro rapporto non deve essere una semplice associazione, ma piuttosto una composizione:

aggiornato diagramma delle classi con la composizione

EF non supporta in modo nativo, ma è possibile emulare il comportamento utilizzando le relazioni di identificazione. Una volta che un'entità è in una relazione identificante a un'entità padre e che il rapporto viene rimosso, l'entità viene rimosso. Sembra che questa è stata la tua intenzione fin dall'inizio. Per ulteriori informazioni su come identificare rapporto, vedi Implementazione identificare le relazioni con EF4 dove ho implementato identificare relazioni con EF4 e hanno collegato a più materiale di lettura.

aggiungere context.DeleteObject(recipe) all'interno del ciclo

Se si effettua la relazione tra bambino e genitore di una segnaletica è possibile rimuovere entità figlio dalla raccolta. Hai bisogno di fare chiave una chiave composta del bambino contenente la chiave primaria id del genitore. In questo modo EF sa che ha bisogno di togliere il bambino.

L'identificazione rapporto fondamentalmente dice che se il genitore non esiste allora il bambino non ha alcun significato. Ciò significa EF sa è sicuro di eliminare il bambino quando il rapporto è stato rimosso.

Vedere questa domanda Identificazione di relazione e l'inserimento di entità figlio cause "Impossibile inserire valore esplicito per la colonna di tabella" e questo e 'possibile rimuovere bambino da collezione e risolvere i problemi su SaveChanges?

Io uso questa estensione al fine di non aggiungere un metodo in DAL solo per eliminare un soggetto (codice preso dal http://blogs.msdn.com/b/alexj/archive/2009/06/ 08 / tip-24-how-to-get-the-ObjectContext-da-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);
}

Così ho quindi eliminare un'entità come Order.Products.Delete(prod).

I vincoli di utilizzare l'estensione sono:
- Ente deve avere rapporti;
-. Entità deve essere allegata alla ObjectContext

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top