更新实体列表的有效方法

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

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

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

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

 //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 entry = Context.Entry(person); entry.State = System.Data.EntityState.Modified; Context.SaveChanges(); } 

应该产量:

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

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

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

应该产量:

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

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

 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 } 

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

我不确定entity framework的beta或RC中的当前版本是否支持批量更新等内容。 但它们是Nuget上EF 4.3.1的扩展

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

希望这可以帮助您实现您的要求

HatSoft已经提到了EntityFramework.Extended。 请看下面基于扩展框架的示例。

http://weblogs.asp.net/pwelter34/archive/2011/11/29/entity-framework-batch-update-and-future-queries.aspx