更新实体列表的有效方法

Ste*_*aly 27 c# sql asp.net-mvc entity entity-framework

我正在开发一个允许用户编辑实体列表的项目.我将这些实体映射到视图模型并使用编辑器字段显示它们.当用户按下提交按钮时,我会浏览每个模型并进行更新,如下所示:

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);
}
Run Code Online (Sandbox Code Playgroud)

上面的代码可以工作,但是你可以看到我们需要为每个实体命中两次数据库(一次检索,另一次更新).使用Entity Framework有更有效的方法吗?我注意到每个更新都会生成一个单独的SQL语句.循环结束后是否有提交所有更新的方法?

Eri*_*ips 20

以下是我所知道的两种更新数据库中的实体而不首先检索实体的方法:

//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();
}
Run Code Online (Sandbox Code Playgroud)

应该产量:

Update [schema].[table]
Set Name = @p__linq__0, BornOn = @p__linq__1
Where id = @p__linq__2
Run Code Online (Sandbox Code Playgroud)

或者,您可以根据需要指定字段(可能适用于具有大量列的表,或出于安全目的,仅允许更新特定列:

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();
}
Run Code Online (Sandbox Code Playgroud)

应该产量:

Update [schema].[table]
Set Name = @p__linq__0
Where id = @p__linq__1
Run Code Online (Sandbox Code Playgroud)

  • 我想突出一个事实,即这是改变质量的最优雅的解决方案,我将保存更改调用移出方法,将其置于循环中以循环访问对象.然后,一旦循环并更改实体,就会调用保存更改. (3认同)

Sla*_*uma 6

您可以尝试以下方法来最小化查询:

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
}
Run Code Online (Sandbox Code Playgroud)

请注意,Contains如果列表viewModels很长,则可能会很慢.但它只会运行一个查询.