2012-07-10 32 views
22

Tôi đang làm việc trên một dự án cho phép người dùng chỉnh sửa danh sách các thực thể. Tôi ánh xạ các thực thể này để xem các mô hình và hiển thị chúng với các trường trình soạn thảo. Khi người dùng nhấn vào nút gửi, tôi đi qua từng mô hình và cập nhật nó như vậy:Cách cập nhật danh sách các thực thể hiệu quả

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

Đoạn mã trên hoạt động, tuy nhiên như bạn có thể thấy chúng ta cần phải nhấn cơ sở dữ liệu hai lần cho mỗi thực thể (một lần để lấy và một bản cập nhật khác). Có cách nào hiệu quả hơn để làm điều này bằng cách sử dụng Entity Framework không? Tôi nhận thấy rằng mỗi bản cập nhật tạo ra một câu lệnh SQL riêng biệt. Có cách nào cam kết tất cả các bản cập nhật sau khi vòng lặp kết thúc không?

+0

Nhìn @ sau liên kết. http://stackoverflow.com/questions/6199211/entity-framework-4-1-batch-updates –

+0

@Saqib Tôi đang cố gắng tránh sử dụng câu lệnh SQL –

Trả lời

16

Dưới đây là hai cách tôi biết để cập nhật một thực thể trong cơ sở dữ liệu mà không làm một hồi của thực thể đầu tiên:

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

nên nhường:

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

Hoặc bạn chỉ có thể xác định các lĩnh vực nếu bạn cần (có thể là tốt cho các bảng với một tấn của các cột, hoặc cho các mục đích an ninh, chỉ cho phép các cột cụ thể để được cập nhật:

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

nên nhường:

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

Tôi không thể tìm thấy phương thức Entry(), nó không phải là một phần của lớp DbSet. Là nó trong một lớp mở rộng? –

+0

Opps không bao giờ liên kết nó trong Context chứ không phải DbSet. Lỗi của tôi. –

+3

Tôi muốn nhấn mạnh thực tế rằng đây là giải pháp thanh lịch nhất để thay đổi về khối lượng, tôi đã di chuyển các thay đổi lưu gọi ra khỏi phương pháp, đặt điều này trong một vòng lặp để lặp qua các đối tượng. Sau đó, một lần lặp và các thực thể được thay đổi, lưu các thay đổi được gọi. – Jay

-1

Tôi không chắc liệu phiên bản hiện tại trong phiên bản beta hay RC của Entity Framework có hỗ trợ một cái gì đó như cập nhật hàng loạt hay không. Nhưng họ là một phần mở rộng cho EF 4.3.1 trên NuGet

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

Hy vọng điều này có thể giúp bạn đạt được yêu cầu của bạn

+1

Sự cố không nhận được nhiều hàng trở lại trong một bài đăng mà người dùng đã chỉnh sửa. Vấn đề là làm thế nào để truy vấn cơ sở dữ liệu một cách hiệu quả để lưu trữ các hàng mà người dùng đã chỉnh sửa. –

5

Bạn có thể thử các follwoing để giảm thiểu các truy vấn:

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 
} 

Hãy nhận biết that Contains can be potentially slow nếu danh sách các viewModels rất dài. Nhưng nó sẽ chỉ chạy một truy vấn duy nhất.

Các vấn đề liên quan