2012-07-10 2 views
22

Ich arbeite an einem Projekt, mit dem der Benutzer eine Liste von Entitäten bearbeiten kann. Ich ordnet diese Entitäten zu, um Modelle anzuzeigen und sie mit Editorfeldern anzuzeigen. Wenn der Benutzer den Absenden-Button drückt, gehe ich jedes Modell durch und aktualisieren Sie es wie folgt:Effiziente Art der Aktualisierung der Liste von Entitäten

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); 
} 

Der obige Code funktioniert, aber wie Sie sehen können wir die Datenbank zweimal für jedes Unternehmen treffen müssen (einmal abrufen und ein anderer zu aktualisieren). Gibt es einen effizienteren Weg, dies mit Entity Framework zu tun? Ich habe festgestellt, dass jedes Update eine separate SQL-Anweisung generiert. Gibt es eine Möglichkeit, alle Updates nach Ablauf der Schleife zu übernehmen?

+0

Schauen Sie @ folgenden Link. http://stackoverflow.com/questions/6199211/entity-framework-4-1-batch-updates –

+0

@Saqib ich SQL-Anweisungen zu vermeiden, versuchen mit –

Antwort

16

Hier gibt zwei Möglichkeiten, die ich kenne, eine Entität in der Datenbank zu aktualisieren, ohne dabei zuerst eine Abfrage der Einheit:

//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(); 
} 

Sollte Ausbeute:

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

Oder Sie können einfach Felder angeben, wenn Sie mit einer Tonne von Spalten für Tabellen (wahrscheinlich gut brauchen, oder für Sicherheitszwecke erlaubt nur bestimmte Spalten aktualisiert werden:

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(); 
} 

ergeben sollten:

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

Ich kann nicht scheinen, die Entry() -Methode zu finden, es ist kein Teil der DbSet-Klasse. Ist es in einer Erweiterungsklasse? –

+0

Opps vergiss es im Kontext nicht das DbSet. Mein Fehler. –

+3

Ich möchte die Tatsache hervorheben, dass dies die eleganteste Lösung ist, um die Masse zu ändern. Ich habe den Aufruf zum Speichern von Änderungen aus der Methode verschoben und in eine Schleife eingefügt, um die Objekte zu durchlaufen. Wenn dann einmal geloopt wird und die Entitäten geändert werden, wird das Speichern der Änderungen aufgerufen. – Jay

-1

Ich bin nicht sicher, ob die aktuelle Version in Beta oder RC von Entity Framework so etwas wie Batch-Update unterstützt. Aber ihr ist eine Erweiterung für EF 4.3.1 auf Nuget

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

Hope this Sie Ihre Anforderung zu erreichen, könnte helfen,

+1

Das Problem ist nicht mehrere Zeilen zurück in einem Post erhalten wird dass der Benutzer bearbeitet hat. Das Problem besteht darin, die Datenbank effizient abzufragen, um die Zeilen zu speichern, die der Benutzer bearbeitet hat. –

5

können Sie versuchen, die Abfragen follwoing zu minimieren:

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 
} 

beachten Sie that Contains can be potentially slow wenn die Liste der viewModels ist sehr lang. Es wird jedoch nur eine einzige Abfrage ausgeführt.