6

Tôi đang cố gắng cập nhật một cơ sở dữ liệu của tôi bằng cách sử dụng ASP.NET Web API và Entity Framework 5 mã đầu tiên, nhưng nó không đang làm việc. Các thực thể của tôi trông giống như sau:Mã EF5 đầu tiên với ASP.NET Web API: Cập nhật thực thể với mối quan hệ nhiều-nhiều

public class CustomerModel 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 

    // More fields 

    public ICollection<CustomerTypeModel> CustomerTypes { get; set; } 
} 

public class CustomerTypeModel 
{ 
    public int Id { get; set; } 
    public string Type { get; set; } 

    [JsonIgnore] 
    public ICollection<CustomerModel> Customers { get; set; } 
} 

Không có gì đặc biệt. Tôi đã xây dựng một giao diện web nơi người dùng có thể thêm khách hàng bằng cách cung cấp tên và kiểm tra một hoặc nhiều loại khách hàng. Khi nhấn nút gửi, dữ liệu được gửi đến phương thức API Web của tôi:

public void Put([FromBody]CustomerModel customer) 
{ 
    using (var context = new MyContext()) 
    { 
     context.Customers.Attach(customer); 
     context.Entry(customer).State = EntityState.Modified; 
     context.SaveChanges(); 
    } 
} 

Điều này cập nhật các trường khách hàng, nhưng loại khách hàng liên quan bị bỏ qua. Các đối tượng đến customer có chứa một danh sách các CustomerTypes nó nên được kết hợp với:

[0] => { Id: 1, Type: "Finance", Customers: Null }, 
[1] => { Id: 2, Type: "Insurance", Customers: Null } 
[2] => { Id: 3, Type: "Electronics", Customers: Null } 

Nhưng thay vì nhìn vào danh sách này và thêm/gỡ bỏ các đơn vị liên quan, EF chỉ cần bỏ qua nó. Các liên kết mới bị bỏ qua và các liên kết hiện có vẫn còn ngay cả khi chúng bị xóa.

Tôi gặp sự cố tương tự khi chèn khách hàng vào cơ sở dữ liệu, điều này đã được khắc phục khi tôi điều chỉnh trạng thái của các thực thể này thành EntityState.Unchanged. Đương nhiên, tôi đã cố gắng áp dụng cùng một sửa chữa ma thuật này trong kịch bản cập nhật của mình:

public void Put([FromBody]CustomerModel customer) 
{ 
    using (var context = new MyContext()) 
    { 
     foreach (var customertype in customer.CustomerTypes) 
     { 
      context.Entry(customertype).State = EntityState.Unchanged; 
     } 

     context.Customers.Attach(customer); 
     context.Entry(customer).State = EntityState.Modified; 
     context.SaveChanges(); 
    } 
} 

Nhưng EF vẫn hiển thị cùng một hành vi.

Bất kỳ ý tưởng nào về cách sửa lỗi này? Hoặc tôi có nên thực sự chỉ cần hướng dẫn rõ ràng trong danh sách CustomerTypes và sau đó thêm chúng theo cách thủ công không?

Xin cảm ơn trước.

JP

Trả lời

10

Điều này không thực sự giải quyết được bằng cách chỉ thiết lập các trạng thái thực thể. Bạn phải tải khách hàng từ cơ sở dữ liệu đầu tiên bao gồm tất cả các loại hiện tại của nó và sau đó loại bỏ các loại từ hoặc thêm các loại cho khách hàng được tải theo bộ sưu tập các loại cập nhật của khách hàng đã đăng. Thay đổi theo dõi sẽ làm phần còn lại để xóa các mục từ bảng tham gia hoặc chèn mục mới:

public void Put([FromBody]CustomerModel customer) 
{ 
    using (var context = new MyContext()) 
    { 
     var customerInDb = context.Customers.Include(c => c.CustomerTypes) 
      .Single(c => c.Id == customer.Id); 

     // Updates the Name property 
     context.Entry(customerInDb).CurrentValues.SetValues(customer); 

     // Remove types 
     foreach (var typeInDb in customerInDb.CustomerTypes.ToList()) 
      if (!customer.CustomerTypes.Any(t => t.Id == typeInDb.Id)) 
       customerInDb.CustomerTypes.Remove(typeInDb); 

     // Add new types 
     foreach (var type in customer.CustomerTypes) 
      if (!customerInDb.CustomerTypes.Any(t => t.Id == type.Id)) 
      { 
       context.CustomerTypes.Attach(type); 
       customerInDb.CustomerTypes.Add(type); 
      } 

     context.SaveChanges(); 
    } 
} 
+0

Yep, tôi sợ cách hướng dẫn này để làm việc. Cảm ơn cho mã, làm việc như một say mê và lưu cho tôi một số thử thách đấu tranh với các tiểu bang :) –

+0

Có cách nào để làm cho chung này vì vậy nó hoạt động cho bất kỳ tài sản chuyển hướng? – CodyK

+0

@Codemiester: Bạn có thể xem qua thư viện GraphDiff được đề cập trong phần bình luận ở đây: http://entityframework.codeplex.com/workitem/864 – Slauma

0

Một giải pháp sạch sẽ là:

public void Put([FromBody]CustomerModel customer) 
{ 
    using (var context = new MyContext()) 
    { 
     var customerInDb = context.Customers.Include(c => c.CustomerTypes) 
      .Single(c => c.Id == customer.Id); 

     // Updates the Name property 
     context.Entry(customerInDb).CurrentValues.SetValues(customer); 

     // Remove types 
     customer.CustomerTypes.Clear(); 

     // Add new types 
     foreach (var type in customer.CustomerTypes) 
     { 
      context.CustomerTypes.Attach(type); 
      customerInDb.CustomerTypes.Add(type); 
     } 

     context.SaveChanges(); 
    } 
} 
+0

Có cách nào để tạo ra loại generic này để nó hoạt động cho bất kỳ thuộc tính điều hướng nào không? – CodyK

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