2012-04-19 33 views
7

Tôi có một ràng buộc duy nhất trên cột của bảng Navigations được gọi là Index. Tôi có hai đối tượng Navigation và tôi muốn hoán đổi các giá trị Index của chúng.Trao đổi các giá trị với ràng buộc duy nhất trong Khung thực thể

Khi tôi gọi db.SaveChanges nó ném một ngoại lệ cho biết ràng buộc duy nhất đã bị vi phạm. Có vẻ như EF đang cập nhật một giá trị và một giá trị khác, do đó vi phạm ràng buộc.

Không nên cập nhật cả hai trong giao dịch và sau đó cố gắng cam kết khi giá trị được sắp xếp và không vi phạm ràng buộc?

Có cách nào để giải quyết vấn đề này mà không sử dụng các giá trị tạm thời không?

+1

Bạn có thể hiển thị dưới dạng một số mã không? – Likurg

+0

bạn cần giá trị tạm thời ở đây, bản cập nhật là hoạt động tự chứa. vì vậy bạn sẽ luôn gặp phải một sự vi phạm ràng buộc, lựa chọn duy nhất khác là vô hiệu hóa các ràng buộc cho hoạt động. –

Trả lời

9

Nó không phải là vấn đề của EF nhưng vấn đề của cơ sở dữ liệu SQL vì lệnh cập nhật được thực thi tuần tự. Giao dịch không có gì để làm với điều này - tất cả các ràng buộc được xác nhận cho mỗi lệnh không cho mỗi giao dịch. Nếu bạn muốn trao đổi các giá trị duy nhất, bạn cần nhiều bước hơn, nơi bạn sẽ sử dụng các giá trị giả bổ sung để tránh tình trạng này.

+0

Điều này có vẻ nguy hiểm vì có khả năng xảy ra sự cố khi đưa ra yêu cầu đồng thời sử dụng cùng một giá trị giả, hoặc có thể là giá trị giả cũng vi phạm ràng buộc. Có một "thực hành tốt nhất" cho tình huống này mà bạn biết không? –

+1

Bạn cũng có thể xóa các bản ghi cũ và tạo các bản ghi mới. Tôi sẽ cố tránh điều này ngay từ đầu.Đó là một tình huống mà ràng buộc duy nhất không phù hợp với nhu cầu logic ứng dụng của bạn. –

+0

Đủ công bằng. Tôi sẽ loại bỏ ràng buộc duy nhất khỏi cơ sở dữ liệu. Nó sẽ không gây ra bất kỳ vấn đề nếu có bản sao. Nếu có, chúng sẽ chỉ theo thứ tự không đáng tin cậy khi được hiển thị trên thanh điều hướng. –

2

Bạn có thể chạy một truy vấn SQL tùy biến để trao đổi các giá trị, như thế này:

update Navigation 
set valuecolumn = 
     case 
      when id=1 then 'value2' 
      when id=2 then 'value1' 
     end 
where id in (1,2) 

Tuy nhiên, Entity Framework không thể làm điều đó, bởi vì nó nằm ngoài phạm vi của một ORM. Nó chỉ thực thi các câu lệnh update tuần tự cho mỗi thực thể bị thay đổi, như Ladislav được mô tả trong câu trả lời của anh ta.

Một khả năng khác là giảm ràng buộc UNIQUE trong cơ sở dữ liệu của bạn và dựa vào ứng dụng để thực thi đúng ràng buộc này. Trong trường hợp này, EF có thể lưu các thay đổi tốt, nhưng tùy thuộc vào kịch bản của bạn, nó có thể không thực hiện được.

3

Có một vài cách tiếp cận. Một số người trong số họ được bao gồm trong các câu trả lời và bình luận khác nhưng để hoàn thành, tôi sẽ liệt kê chúng ra ở đây (lưu ý rằng đây chỉ là một danh sách mà tôi động não và nó có thể không được tất cả những gì 'hoàn thành').

  1. Thực hiện tất cả các cập nhật trong một lệnh. Xem W0lf's answer để biết ví dụ về điều này.
  2. Thực hiện hai bộ cập nhật - một để hoán đổi tất cả các giá trị thành giá trị âm của giá trị dự định và sau đó một giây để hoán đổi chúng từ âm sang dương. Điều này là làm việc trên các giả định rằng các giá trị âm không bị ngăn cản bởi các ràng buộc khác và rằng chúng không phải là các giá trị mà các bản ghi khác với các giá trị trong trạng thái tạm thời sẽ có.
  3. Thêm cột phụ - Ví dụ: Cập nhật - đặt thành cột phụ trong tập hợp các bản cập nhật đầu tiên nơi các giá trị được thay đổi và sau đó đặt lại thành giá trị sai trong tập hợp cập nhật thứ hai. Hoán đổi ràng buộc duy nhất cho chỉ mục được lọc, duy nhất bỏ qua các bản ghi trong đó IsUpdating là đúng.
  4. Xóa ràng buộc và xử lý các giá trị trùng lặp.
+0

Ý tưởng thiết lập thành tiêu cực sau đó trở lại tích cực là thông minh và đã làm cho các trick cho tôi. Cảm ơn! – jslatts

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