2014-05-09 8 views
15

Ho un modello di vista che incapsula solo di alcune delle proprietà del modello di database. Queste proprietà contenute nel modello di visualizzazione sono le sole proprietà che voglio aggiornare. Voglio che le altre proprietà conservino il loro valore.Entity Framework 6.1 Aggiornamento di un sottoinsieme di un record

Durante la mia ricerca ho trovato la risposta this che sembra essere perfetta per le mie esigenze, tuttavia, nonostante i miei migliori sforzi, non riesco a far funzionare il codice come previsto.

Ecco un esempio isolato di quello che mi si avvicinò con:

static void Main() { 
    // Person with ID 1 already exists in database. 

    // 1. Update the Age and Name. 
    Person person = new Person(); 
    person.Id = 1; 
    person.Age = 18; 
    person.Name = "Alex"; 

    // 2. Do not update the NI. I want to preserve that value. 
    // person.NINumber = "123456"; 

    Update(person); 
} 

static void Update(Person updatedPerson) { 
    var context = new PersonContext(); 

    context.Persons.Attach(updatedPerson); 
    var entry = context.Entry(updatedPerson); 

    entry.Property(e => e.Name).IsModified = true; 
    entry.Property(e => e.Age).IsModified = true; 

    // Boom! Throws a validation exception saying that the 
    // NI field is required. 
    context.SaveChanges(); 
} 

public class PersonContext : DbContext { 
    public DbSet<Person> Persons { get; set; } 
} 

public class Person { 
    public int Id { get; set; } 
    [Required] 
    public string Name { get; set; } 
    [Required] 
    public int Age { get; set; } // this is contrived so, yeah. 
    [Required] 
    public string NINumber { get; set; } 
} 

Che cosa sto facendo di sbagliato?

+1

Perché si collega la persona? Generalmente quando lavoro con il framework di entità, recupero il record, modifico le sue proprietà ed eseguo SaveChanges(); Qualcosa come: Person person = context.People.First(); person.Name = "John"; context.SaveChanges(); – Areks

+0

Poiché ciò richiederebbe due query sul database + in realtà, sto utilizzando un repository generico. –

+1

Questo non è davvero un repository generico, ma comunque, +1 per @Areks ha detto. Se sei preoccupato per 2 query allora hai altri problemi – mituw16

risposta

4

Si basa il proprio lavoro sulla post https://stackoverflow.com/a/15339512/2015959, ma in altro thread i campi che non sono stati modificati (e in quanto tali non erano nel modello allegato) non fosse obbligatorio, ed è per questo che ha funzionato . Poiché i tuoi campi sono obbligatori, riceverai questo errore di convalida.

Il tuo problema può essere risolto con la soluzione fornita in questione Entity Framework validation with partial updates

+0

Hey Radu, grazie per essere così specifico. Il secondo link è esattamente il problema che stavo avendo. – Jono

0

(A cura per chiarezza)

Il contesto deve avere una copia completa dell'oggetto di far rispettare le regole di business. Questo può accadere solo se l'oggetto associato ha tutte le proprietà necessarie popolate o la vista parziale è unita a una copia completa prima dell'aggiornamento.

Credo che ciò che si vuole fare sia concettualmente impossibile: fare aggiornamenti come questo richiederà una copia pre-change preservata, o due query al database perché il livello aziendale ha bisogno di una copia completa dell'oggetto per la convalida.

+0

Potrebbe citare una fonte? Penso * che [questa risposta] (http://stackoverflow.com/questions/15336248/entity-framework-5-updating-a-record/15339512#15339512) suggerisca diversamente. –

+1

non è così. puoi applicare le regole aziendali solo per i campi modificati. guarda la mia risposta – jltrem

+0

@ jltrem- sì, è possibile disabilitare la convalida del record ed è possibile verificare la proprietà di convalida a livello di campo (obbligatorio, intervallo, ecc.). Ma questo metodo non funzionerà per un oggetto con regole a livello di record (IValidatableObject o ValidateEntity), che possono richiedere tutti i valori dell'entità per passare. In entrambi i casi, ignorando la convalida del livello aziendale è necessario ricorrere al database per assicurarsi che i dati non validi non vengano inseriti. Suppongo che il mio post originale avrebbe dovuto dire "concettualmente impossibile in un design responsabile"? – esmoore68

2

È la convalida che sta causando di non essere salvato. È possibile disabilitare la convalida con context.Configuration.ValidateOnSaveEnabled = false; e funzionerà. Per convalidare campi specifici è possibile chiamare var error = entry.Property(e => e.Name).GetValidationErrors();. Pertanto, è possibile creare un metodo "UpdateNameAndAge" che applica solo le regole aziendali e contrassegna tali proprietà come modificate. Nessuna doppia richiesta richiesta.

private static bool UpdateNameAndAge(int id, string name, int age) 
    { 
    bool success = false; 

    var context = new PersonContext(); 
    context.Configuration.ValidateOnSaveEnabled = false; 

    var person = new Person() {Id = id, Name = name, Age = age}; 
    context.Persons.Attach(person); 
    var entry = context.Entry(person); 

    // validate the two fields 
    var errorsName = entry.Property(e => e.Name).GetValidationErrors(); 
    var errorsAge = entry.Property(e => e.Age).GetValidationErrors(); 

    // save if validation was good 
    if (!errorsName.Any() && !errorsAge.Any()) 
    { 
     entry.Property(e => e.Name).IsModified = true; 
     entry.Property(e => e.Age).IsModified = true; 

     if (context.SaveChanges() > 0) 
     { 
      success = true; 
     } 
    } 

    return success; 
    }