Come ripulire un contesto di oggetto Entity Framework?

c# entity-framework

Domanda

Sto aggiungendo diverse entità a un contesto di oggetto.

try
{
    forach (var document in documents)
    {
        this.Validate(document); // May throw a ValidationException.

        this.objectContext.AddToDocuments(document);
    }

    this.objectContext.SaveChanges();
}
catch
{
    // How to clean-up the object context here?

    throw;
}

Se alcuni dei documenti superano la convalida e uno non riesce, tutti i documenti che hanno superato la convalida rimangono aggiunti al contesto dell'oggetto. Devo ripulire il contesto dell'oggetto perché potrebbe essere riutilizzato e può succedere quanto segue.

var documentA = new Document { Id = 1, Data = "ValidData" };
var documentB = new Document { Id = 2, Data = "InvalidData" };
var documentC = new Document { Id = 3, Data = "ValidData" };

try
{
    // Adding document B will cause a ValidationException but only
    // after document A is added to the object context.
    this.DocumentStore.AddDocuments(new[] { documentA, documentB, documentC });
}
catch (ValidationException)
{
}

// Try again without the invalid document B. This causes an exception because
// of a duplicate primary key - document A with id 1 is added a second time.
this.DocumentStore.AddDocuments(new[] { documentA, documentC });

Ciò aggiungerà nuovamente il documento A al contesto dell'oggetto e di conseguenza SaveChanges() genererà un'eccezione a causa di una chiave primaria duplicata.

Quindi devo rimuovere tutti i documenti già aggiunti nel caso di un errore di convalida. Naturalmente, potrei eseguire la convalida e aggiungere tutti i documenti solo dopo che sono stati convalidati correttamente, ma purtroppo questo non risolve l'intero problema: se SaveChanges() fallisce, tutti i documenti rimangono comunque aggiunti ma non salvati.

Ho provato a staccare tutti gli oggetti restituiti da

 this.objectContext.ObjectStateManager.GetObjectStateEntries(EntityState.Added)

ma ricevo un'eccezione che indica che l'oggetto non è collegato. Quindi, come faccio a sbarazzarmi di tutti gli oggetti aggiunti ma non salvati?

Risposta accettata

Era solo un bug insignificante, ma ho intenzione di lasciare la domanda qui - forse aiuta gli altri.

Ho avuto il seguente

var objectStateEntries = this.objectContext
                             .ObjectStateManager
                             .GetObjectStateEntries(EntityState.Added);

foreach (var objectStateEntry in objectStateEntries)
{
    this.objectContext.Detach(objectStateEntry);
}

mentre volevo il seguente

foreach (var objectStateEntry in objectStateEntries)
{
    this.objectContext.Detach(objectStateEntry.Entity);
}

e non potevo vederlo.


Risposta popolare

La risposta di Daniel ha funzionato per me, tuttavia l'API EntityFramework è diversa nella versione 6+. Ecco un metodo che ho aggiunto al mio contenitore del repository personalizzato che scollegherà tutte le entità dal ChangeTracker di DbContext:

    /// <summary>
    /// Detaches all of the DbEntityEntry objects that have been added to the ChangeTracker.
    /// </summary>
    public void DetachAll() {

        foreach (DbEntityEntry dbEntityEntry in this.Context.ChangeTracker.Entries()) {

            if (dbEntityEntry.Entity != null) {
                dbEntityEntry.State = EntityState.Detached;
            }
        }
    }


Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché
Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché