我正在开发一个允许用户编辑实体列表的项目。我将这些实体映射到视图模型并使用编辑器字段显示它们。当用户按下提交按钮时,我会浏览每个模型并进行更新,如下所示:
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语句。有没有办法在循环结束后提交所有更新?
答案 0 :(得分:19)
我知道有两种方法可以更新数据库中的实体而不首先检索实体:
//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();
}
应该屈服:
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<Person> 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
答案 1 :(得分: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
}
如果viewModels
的列表很长,请注意that Contains
can be potentially slow。但它只会运行一个查询。
答案 2 :(得分:-1)
我不确定实体框架的测试版或RC中的当前版本是否支持批量更新等内容。但它们是Nuget上的EF 4.3.1的扩展
http://nuget.org/packages/EntityFramework.Extended
希望这可以帮助您实现您的要求
答案 3 :(得分:-1)
HatSoft已经提到了EntityFramework.Extended。请看下面基于扩展框架的示例。