2012-07-10 16 views
22

Estoy trabajando en un proyecto que permite al usuario editar una lista de entidades. Mapeo estas entidades para ver modelos y mostrarlos con campos de editor. Cuando el usuario pulsa el botón de enviar, voy a través de cada modelo y actualizarlo, así:Modo eficiente de actualizar la lista de entidades

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

El código anterior funciona, sin embargo, como se puede ver que necesitamos para golpear la base de datos dos veces por cada entidad (una vez para recuperar y otro para actualizar). ¿Hay alguna manera más eficiente de hacerlo utilizando Entity Framework? Noté que cada actualización genera una declaración SQL separada. ¿Hay alguna forma de confirmar todas las actualizaciones después de que el ciclo haya terminado?

+0

Mirar @ following link. http://stackoverflow.com/questions/6199211/entity-framework-4-1-batch-updates –

+0

@Saqib que estoy tratando de evitar el uso de sentencias SQL –

Respuesta

16

Aquí hay dos maneras que conozco para actualizar una entidad en la base de datos sin hacer una recuperación de la entidad primero:

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

caso de rendimiento:

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

O simplemente puede especificar campos si es necesario (probablemente bueno para tablas con una tonelada de columnas, o con fines de seguridad, permite que sólo las columnas específicas que se actualizan:

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

debe ceder:

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

Parece que no puedo encontrar el método Entry(), no es parte de la clase DbSet. ¿Está en una clase de extensión? –

+0

Opps no importa en el Contexto, no en el DbSet. Mi error. –

+3

Me gustaría resaltar el hecho de que esta es la solución más elegante para cambiar en masa, moví la llamada a guardar cambios fuera del método, puse esto en un bucle para recorrer los objetos. Luego, una vez en bucle y las entidades cambian, se llama guardar cambios. – Jay

-1

No estoy seguro de si la versión actual en versión beta o RC de Entity Framework es compatible con algo así como la actualización por lotes. Pero su es una extensión para EF 4.3.1 en Nuget

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

la esperanza que esto podría ayudar a alcanzar su requerimiento

+1

El problema no es obtener varias filas atrás en un puesto que el usuario editó El problema es cómo consultar la base de datos de manera eficiente para almacenar las filas editadas por el usuario. –

5

puede probar el follwoing para minimizar consultas:

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 
} 

Tenga en cuenta that Contains can be potentially slow si la lista de viewModels es muy largo. Pero solo ejecutará una sola consulta.

Cuestiones relacionadas