2011-10-18 25 views
5

Tôi đang sử dụng mã khung thực thể đầu tiên và hiển thị cơ sở dữ liệu Northwind thông qua giao diện WCF REST HTTP.Reattaching một đồ thị thực thể và phát hiện thay đổi bộ sưu tập

Tôi đã không tiếp xúc với bảng OrderDetails (các mục đặt hàng) vì nó không có ý nghĩa khi tạo một đơn hàng và sau đó thêm mỗi OrderDetail theo yêu cầu riêng biệt thông qua một dịch vụ khác. Theo tôi, nó cần phải là một giao dịch nguyên tử hoặc thành công hoặc thất bại. Vì vậy, tôi bao gồm bộ sưu tập Order.OrderDetails khi chuyển đến máy khách và giả sử tôi sẽ nhận được một khi một đơn đặt hàng được tạo hoặc cập nhật.

Tuy nhiên, sự cố có vẻ như đang phát hiện các thay đổi đối với bộ sưu tập OrderDetails khi gắn lại thực thể Đơn hàng để cập nhật. Bản thân thứ tự có thể được thiết lập như được sửa đổi để cập nhật các thuộc tính này nhưng điều này không xếp vào các mục OrderDetail. Vì vậy, tôi có thể tự đi qua và thiết lập những cập nhật để sửa đổi nhưng vấn đề nằm trong việc tìm ra những cái được cập nhật ở nơi đầu tiên. Đặt một OrderDetail mới để sửa đổi sẽ gây ra lỗi khi cố lưu.

Tôi đọc một đề xuất để đặt Id của các mục bộ sưu tập mới thành 0 và trong máy chủ sử dụng để quyết định xem nó mới hay hiện có. Tuy nhiên, Northwind sử dụng khóa tổng hợp giữa OrderID và ProductID cho OrderDetails. Cả hai sẽ phải được thiết lập bởi khách hàng, vì vậy tôi không thể tìm thấy một cách để phát hiện những gì mới. Hơn nữa, một OrderDetail đã xóa sẽ không tồn tại trong biểu đồ tách rời và tôi sẽ cần phải tìm ra những gì đã bị xóa và loại bỏ nó một cách rõ ràng.

Mọi lời khuyên sẽ được đánh giá cao.

public override Order Update(Order entity) 
{ 
    dbset.Attach(entity); 
    DataContext.Entry(entity).State = EntityState.Modified; 

    foreach (var orderDetail in entity.OrderDetails) 
    { 
     DataContext.Entry(orderDetail).State = EntityState.Modified; 
    } 

    return entity; 
} 

Trả lời

4

Đây là common and complex issue và không có phép thuật nào sẽ làm điều đó cho bạn. Giải pháp của tôi (và là người duy nhất mà làm việc trong tất cả các kịch bản) là để nạp Order một lần nữa trong phương pháp cập nhật của bạn và tự nhập các thay đổi:

public override Order Update(Order entity) 
{ 
    // No attach of entity 

    var attached = DataContext.Orders.Include(o => o.OrderDetails).SingleOrDefault(...); 
    if (attached == null) ... 

    // Merge changes from entity to attached - if you change any property 
    // it will be marked as modified automatically 

    foreach (var detail in attached.OrderDetails.ToList()) 
    { 
     // ToList is necessary because you will remove details from the collection 

     // if detail exists in entity check if it must be updated and set its state 

     // if detail doesn't exists in entity remove if from collection - if it is \ 
     // aggregation (detail cannot exists without Order) you must also delete it 
     // from context to ensure it will be deleted from the database 
    } 

    foreach (var detail in entity.OrderDetails) 
    { 
     // if it doesn't exists in attached create new detail instance, 
     // fill it from detail in entity and add it to attached entity - 
     //you must not use the same instance you got from the entity 
    } 

    DataContext.SaveChanges(); 

    return entity; 
} 

Có thể có cũng cần phải tự kiểm tra timestamps nếu bạn sử dụng chúng.

Kịch bản thay thế là những gì bạn đã mô tả với 0 được sử dụng cho chi tiết mới và ID âm cho chi tiết đã xóa nhưng đó là logic phải được thực hiện trên máy khách. Nó cũng chỉ hoạt động trong một số trường hợp.

+0

Câu trả lời hay. Cảm ơn đã dành thời gian! –

+0

Đừng cho rằng bạn có bất kỳ ý tưởng nào tại sao nhóm EF quyết định không theo đuổi kịch bản đính kèm đồ thị thực thể và làm cho nó tự động hơn một chút? Tôi nghĩ rằng nó có thể là do không muốn cho phép khách hàng cập nhật, nói Product trong một Order - OrderItem - Product scenario. –

+0

Tôi càng nghĩ về vấn đề này thì càng tin rằng tự động hóa đầy đủ là không thể hoặc đáng tin cậy (độ tin cậy chính xác là những gì bạn mô tả - cập nhật tự động có thể sửa đổi các thực thể mà bạn không muốn sửa đổi). –

6

Gần đây tôi đã được phép mở nguồn một số công việc tôi đã làm cho chủ nhân của tôi một thời gian trước đây (với một số thay đổi của khóa học). Tôi thực sự đã viết một phương pháp mở rộng để giải quyết vấn đề này, bạn có thể lấy nó tại http://refactorthis.wordpress.com/2012/12/11/introducing-graphdiff-for-entity-framework-code-first-allowing-automated-updates-of-a-graph-of-detached-entities/

Hy vọng điều đó sẽ hữu ích!

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