2012-07-10 18 views
22

我正在研究一個允許用戶編輯實體列表的項目。我將這些實體映射到查看模型並使用編輯器字段顯示它們。當用戶按下提交按鈕,我經過的每個模型並對其進行更新,像這樣:更新實體列表的有效方法

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

請看@下面的鏈接。 http://stackoverflow.com/questions/6199211/entity-framework-4-1-batch-updates – 2012-07-10 20:49:12

+0

@Saqib我試圖避免使用SQL語句 – 2012-07-11 13:17:25

回答

16

這裏有兩種方法,我知道的沒有做更新數據庫中的實體實體第一的檢索:

//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 
+0

我似乎無法找到Entry()方法,它不是DbSet類的一部分。它在擴展類中嗎? – 2012-07-11 13:16:03

+0

Opps在上下文中不會意識到DbSet。我的錯。 – 2012-07-11 13:20:52

+3

我想強調這是改變質量的最優雅的解決方案,我將保存更改調用移出該方法,並將其放入一個循環中循環遍歷對象。然後一旦循環並更改實體,則保存更改被調用。 – Jay 2015-03-24 11:14:36

-1

我不確定實體框架的測試版或RC中的當前版本是否支持批量更新。但他們是對的NuGet

爲EF 4.3.1的擴展

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

希望這可以幫助你實現你的要求

+1

這個問題不得到多行早在一個職位用戶編輯。問題是如何有效地查詢數據庫以存儲用戶編輯的行。 – 2012-07-10 20:35:42

5

你可以嘗試follwoing減少查詢:

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 
} 

注意that Contains can be potentially slow如果viewModels列表很長。但它只會運行一個查詢。