2015-08-04 19 views
6

Sto cercando di capire come eseguire senza problemi un aggiornamento parziale (fondamentalmente un HTTP PATCH) di un'entità, utilizzando Entity Framework 6.0, ma sono perplesso rispetto al numero di esempi disponibili che non sembra funzionare per me (anche quelli che non sono ovviamente per un'altra versione di EF).Aggiornamento parziale di un'entità in EF6

Quello che mi piacerebbe da compiere:

  • L'entità viene aggiornato senza dover caricare in primo luogo; cioè c'è un solo viaggio al database solo
  • le proprietà che ho touch sono aggiornati - gli altri sono lasciati come è

Il più vicino che ho ottenuto è ben descritto da this answer ad una domanda molto simile, e illustrato dal codice seguente:

public async Task UpdateMyEntity(int id, int? updatedProperty, string otherProperty) 
{ 
    using (var context = new MyDbContext()) 
    { 
     var entity = new MyEntity { Id = id }; 
     context.MyEntities.Attach(entity); 

     if (updatedProperty != null) { entity.Property = updatedProperty.Value; } 
     if (!string.IsNullOrEmpty(otherProperty) { entity.OtherProperty = otherProperty; } 

     await context.SaveChangesAsync(); 
    } 
} 

Ora, questo funziona per le entità semplici, ma sto ottenendo gli errori di convalida entità perché ho un paio di proprietà e relazioni richieste che non sono aggiornate e quindi non presente nel soggetto annesso . Come notato, vorrei semplicemente ignorare quelli.

ho il debug e verificato che context.Entry(entity).Property(e => e.Property).IsModified modifiche a true quando quella linea viene eseguito, e che tutte le proprietà che non ho mai toccare ancora tornare false per i controlli simili, così ho pensato EF sarebbe in grado di gestire questa situazione.

È possibile risolvere questo problema con i due vincoli sopra riportati? Come?


Aggiornamento:

Con s' answerLSU.Net Capisco un po' quello che devo fare, ma non funziona completamente. La logica fallisce per le proprietà referenziali.

Si consideri il seguente modello di dominio:

public class MyEntity 
{ 
    public int Id { get; set; } 
    public int Property { get; set; } 
    [Required] 
    public string OtherProperty { get; set; } 
    [Required] 
    public OtherEntity Related { get; set; } 
} 

public class OtherEntity 
{ 
    public int Id { get; set; } 
    public string SomeProperty { get; set; } 
} 

Ora, se cerco di aggiornare un MyEntity, faccio la seguente:

var entity = new MyEntity { Id = 123 }; // an entity with this id exists in db 
context.MyEntities.Attach(entity); 

if (updatedProperty != null) { entity.Property = updatedProperty.Value; } 

await context.SaveChangesAsync(); 

Nel mio metodo di convalida personalizzato, ignorato come in the answer below, l'errore di convalida sulla proprietà richiesta OtherProperty viene rimosso correttamente, poiché non viene modificato. Tuttavia, ottengo ancora un errore di convalida sulla proprietà Related, perché entityEntry.Member("Related") is DbReferenceEntry, non DbPropertyEntry, e quindi l'errore di convalida non è contrassegnato come falso errore.

Ho provato ad aggiungere una clausola separata, analoga per la gestione delle proprietà di riferimento, ma lo entityEntry non sembra contrassegnare quelli modificati; con relation = member as DbReferenceEntry, relation non ha nulla per indicare che la relazione è cambiata.

In questo caso è possibile verificare la presenza di errori falsi? Ci sono altri casi che devo gestire specialmente (relazioni uno-a-molti, per esempio)?

risposta

2

Entity Framework validation with partial updates

@Shimmy ha scritto un certo codice qui per omettere la logica di convalida per le proprietà non modificati. Potrebbe funzionare per te.

protected override DbEntityValidationResult ValidateEntity(
    DbEntityEntry entityEntry, 
    IDictionary<object, object> items) 
{ 
    var result = base.ValidateEntity(entityEntry, items); 
    var falseErrors = result.ValidationErrors 
    .Where(error => 
    { 
     var member = entityEntry.Member(error.PropertyName); 
     var property = member as DbPropertyEntry; 
     if (property != null) 
     return !property.IsModified; 
     else 
     return false;//not false err; 
    }); 

    foreach (var error in falseErrors.ToArray()) 
    result.ValidationErrors.Remove(error); 
    return result; 
} 
+0

Questo è ottimo, ma non riesce ancora a rimuovere gli errori di convalida per proprietà referenziali non toccate. Aggiornerò l'OP per mostrare un caso d'uso. –

+0

Si prega di consultare il mio aggiornamento :) Altre idee sono i benvenuti! –

Problemi correlati