2012-07-10 14 views
22

Sto lavorando a un progetto che consente all'utente di modificare un elenco di entità. Mappo queste entità per visualizzare i modelli e visualizzarli con i campi dell'editor. Quando l'utente preme il pulsante di invio, vado attraverso ogni modello e aggiornare in questo modo:Modo efficiente di aggiornare l'elenco delle entità

foreach (var viewModel in viewModels) 
{ 
    //Find the database model and set the value and update 
    var entity = unit.EntityRepository.GetByID(fieldModel.ID); 
    entity.Value = viewModel.Value; 
    unit.EntityRepository.Update(entity); 
} 

Il codice precedente funziona, ma come potete vedere abbiamo bisogno di colpire la base di dati due volte per ogni entità (una volta per recuperare e un altro da aggiornare). Esiste un modo più efficiente per farlo utilizzando Entity Framework? Ho notato che ogni aggiornamento genera un'istruzione SQL separata. C'è un modo di impegnare tutti gli aggiornamenti dopo che il ciclo è finito?

+0

Look @ seguente collegamento. http://stackoverflow.com/questions/6199211/entity-framework-4-1-batch-updates –

+0

@Saqib sto cercando di evitare di usare le istruzioni SQL –

risposta

16

Qui ci sono due modi che conosco per aggiornare un'entità nel database senza fare un recupero dell'entità primo:

//Assuming person is detached from the context 
//for both examples 
public class Person 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
    public DateTime BornOn { get; set; } 
} 

public void UpdatePerson(Person person) 
{ 
    this.Context.Persons.Attach(person) 
    DbEntityEntry<Person> entry = Context.Entry(person); 
    entry.State = System.Data.EntityState.Modified; 
    Context.SaveChanges(); 
} 

dovrebbe produrre:

Update [schema].[table] 
Set Name = @p__linq__0, BornOn = @p__linq__1 
Where id = @p__linq__2 

Oppure si può semplicemente specificare i campi se è necessario (probabilmente un bene per le tabelle con una tonnellata di colonne, o per motivi di sicurezza, consente solo colonne specifiche da aggiornare:

public void UpdatePersonNameOnly(Person person) 
{ 
    this.Context.Persons.Attach(person) 
    DbEntityEntry<Person> entry = Context.Entry(person); 
    entry.Property(e => e.Name).IsModified = true; 
    Context.SaveChanges(); 
} 

dovrebbe produrre:

Update [schema].[table] 
Set Name = @p__linq__0 
Where id = @p__linq__1 
+0

Non riesco a trovare il metodo Entry(), non fa parte della classe DbSet. È in una classe di estensione? –

+0

Il contrario non è nel contesto, non nel DbSet. Colpa mia. –

+3

Vorrei sottolineare il fatto che questa è la soluzione più elegante per il cambiamento di massa, ho spostato le modifiche di salvataggio richiamate dal metodo, inserendo questo in un ciclo per scorrere gli oggetti. Quindi, una volta in loop e le entità vengono modificate, viene richiamato il salvataggio delle modifiche. – Jay

-1

Non sono sicuro se la versione corrente in beta o RC di Entity Framework supporti qualcosa come l'aggiornamento in batch. Ma la loro è un'estensione per EF 4.3.1 su Nuget

http://nuget.org/packages/EntityFramework.Extended

Spero che questo potrebbe aiutare a raggiungere il vostro requisito

+1

Il problema non è ottenere più righe di nuovo in un post che l'utente ha modificato. Il problema è come interrogare il database in modo efficiente per memorizzare le righe modificate dall'utente. –

5

È possibile provare il follwoing per ridurre al minimo le query:

using (var ctx = new MyContext()) 
{ 
    var entityDict = ctx.Entities 
     .Where(e => viewModels.Select(v => v.ID).Contains(e.ID)) 
     .ToDictionary(e => e.ID); // one DB query 

    foreach (var viewModel in viewModels) 
    { 
     Entity entity; 
     if (entityDict.TryGetValue(viewModel.ID, out entity)) 
      entity.Value = viewModel.Value; 
    } 

    ctx.SaveChanges(); //single transaction with multiple UPDATE statements 
} 

essere consapevoli that Contains can be potentially slow se l'elenco dei viewModels è molto lungo Ma eseguirà solo una singola query.

Problemi correlati