2012-03-08 39 views
11

Bảng của tôi Sections (Máy chủ SQL) có ID làm khóa chính (int, identity)SortIndex cột (int) cho mục đích sắp xếp.Khuôn khổ thực thể không cập nhật giá trị được sửa đổi bởi kích hoạt

Cơ sở dữ liệu có trình kích hoạt đặt SortIndex := ID ở mỗi INSERT. Rõ ràng là tôi muốn thay đổi chỉ mục sắp xếp sau, bằng cách hoán đổi các giá trị cho hai hàng.

Tôi truy cập dữ liệu bằng cách sử dụng Khung thực thể, tất cả đều có ứng dụng web MVC3.

Vấn đề là, Entity Framework không cập nhật giá trị SortIndex sau khi tôi chèn một đối tượng mới vào bảng. Nó cũng lưu trữ tất cả dữ liệu, vì vậy cuộc gọi sau để nhận tất cả các đối tượng từ bảng này cũng sẽ cung cấp giá trị sai cho giá trị SortIndex cho đối tượng này.

Tôi đã thử thay đổi StoreGeneratedPattern cho cột này trong EDMX. Điều này có vẻ là tuyệt vời và thanh lịch nhưng không giải quyết được vấn đề.

Nếu tôi đặt thành Identity, nó làm cho EF cập nhật đúng giá trị, nhưng nó trở thành chỉ đọc (ngoại lệ được ném khi cố thay đổi). Đặt nó thành Computed là tương tự, nhưng thay vì ngoại lệ được ném các giá trị chỉ không được ghi vào DB.

tôi có thể tái tạo lại đối tượng EF mỗi lần nếu tôi cần phải sử dụng nó sau khi chèn một đối tượng, chỉ bằng cách làm:

DatabaseEntities db = new DatabaseEntities() 

Nhưng nó có vẻ như workaround xấu xí cho tôi.

Giải pháp cho vấn đề này là gì?

Rõ ràng là điều gì đó, những gì không yêu cầu tôi phải thực hiện một số hành động sau mỗi insert (và có nguy cơ bị lãng quên và không được chú ý) được ưu tiên.

+0

có thể trùng lặp: http://stackoverflow.com/questions/5445243/reload-field-value-modified-in-db-by-trigger-sau-chèn-cập nhật –

+0

Nó tương tự, nhưng anh ta dường như có một lĩnh vực mà anh ta không cần phải viết. "Tính toán" sẽ tốt cho anh ta. Nó không hoạt động vì một số lỗi. – Arek

Trả lời

15

Trong ngắn StoreGeneratedPattern có nghĩa là: giá trị được xử lý bởi cửa hàng và ứng dụng của bạn sẽ không bao giờ sửa đổi nó. Trong trường hợp này, bạn sẽ tự động nhận được giá trị do cửa hàng tạo ra sau khi gọi SaveChanges.

Nếu bạn không sử dụng StoreGeneratedPattern bạn sẽ không nhận được giá trị và bạn sẽ phải buộc thực thi truy vấn khác để làm mới thực thể của bạn. Bạn có thể ví dụ làm:

objectContext.Refresh(RefreshMode.StoreWins, yourSection); 

Nói chung tình huống mà bạn cần phải cập nhật giá trị trong cả hai cơ sở dữ liệu thông qua trigger và ứng dụng không chơi rất độc đáo với EF (và có lẽ cũng công cụ ORM khác).

+0

Cảm ơn mã 'Refresh', nó trông đẹp hơn việc tái tạo đối tượng EF. Thật không may tôi không thể bỏ phiếu với danh tiếng của tôi. – Arek

+0

@Bạn có thể chấp nhận câu trả lời –

+0

Tôi biết tôi có thể chấp nhận, nhưng tôi đang thử nghiệm một số giải pháp khả thi khác ở đây, vì vậy chưa. – Arek

0

Bạn có biết mình sẽ làm việc với cột đó một lần nữa trong cùng một yêu cầu không?

Tôi sẽ sử dụng ngữ cảnh cho mỗi trường hợp yêu cầu, thường giúp bạn thoát khỏi nhiều vấn đề, vì ngữ cảnh EF mới được tạo với mọi yêu cầu, do đó bạn có dữ liệu mới một lần theo yêu cầu.

Với bối cảnh sống lâu, có thể phát triển sự không nhất quán như bạn đã mô tả.

Dù sao, StoreGeneratedPattern được đặt thành tính toán phải chính xác. Nhưng nó tự cập nhật chỉ khi bạn đang lưu trữ thực thể thực tế. Nó không được cập nhật bằng cách chèn hoặc cập nhật bất kỳ thực thể nào khác.

từ http://msdn.microsoft.com/en-us/library/dd296755(v=vs.90).aspx

Nếu bạn tạo một thực thể mới hoặc thay đổi một thực thể đang tồn tại, các giá trị của các thuộc tính với StoreGeneratedPattern thiết lập để Điện Toán được lấy ra từ máy chủ khi bạn gọi phương thức SaveChanges trong ứng dụng của bạn. Nếu bạn chỉ định giá trị cho thuộc tính có StoreGeneratedPattern được đặt thành Được tính trong ứng dụng của bạn, giá trị sẽ được ghi đè bằng giá trị do máy chủ tạo khi bạn gọi phương thức SaveChanges.

Chúng tôi đang sử dụng tùy chọn giá trị được tính cho GUID được sắp xếp theo trình tự SQL và nó hoạt động OK.

+0

Điều tôi đang làm là (1) thêm đối tượng mới, (2) nhận và trả lại tất cả các đối tượng được sắp xếp theo SortIndex để cập nhật trang web. Vì vậy, có, tôi đang sử dụng SortIndex một lần nữa trong cùng một yêu cầu. – Arek

+0

Và StoreGeneratedPattert = Tính toán - điều này dường như cập nhật đối tượng đúng cách, nhưng tôi không thể sửa đổi SortIndex nữa. Tôi cố gắng, nhưng sau khi tôi làm SaveChanges() giá trị cũ được khôi phục. Có vẻ như EF chỉ lặng lẽ bỏ qua những thay đổi này. – Arek

+0

Có, lưu trữGenerated rõ ràng nói rằng nó được tạo ra trong cửa hàng, do đó, nó không bận tâm để viết nó. Có lẽ tốt nhất cho bạn sẽ được thiết lập entity.SortIndex = entity.id ngay sau khi lưu, sau đó bạn có thể làm việc với nó như bạn muốn. –

2

Tôi tìm thấy câu trả lời từ 'Ladislav Mrnka' chính xác và đánh dấu là đã được chấp nhận. Dưới đây là các cách giải quyết khác, mà tôi tìm thấy trong khi cố gắng tìm một số giải pháp. Tuy nhiên, giải pháp tôi đang tìm kiếm nói chung là không thể.

Một trong những khả năng là đặt StoreGeneratedPattern = Computed để cho EF biết, giá trị này được tính toán. Và sau đó, hãy thực hiện Quy trình được lưu trữ để thực sự thay đổi giá trị của SortIndex. Thông thường nó sẽ thay đổi giá trị trong hai hàng (hoán đổi chúng), để thay đổi thứ tự sắp xếp. Thủ tục này cùng với một kích hoạt tại INSERT đảm bảo dữ liệu vẫn nhất quán trong DB. Không thể tạo hàng mới mà không có giá trị thích hợp được đặt trong SortIndex, không thể tạo hai đối tượng có cùng giá trị (trừ khi quy trình được lưu trữ có lỗi) và không thể phá giá trị theo cách thủ công bằng cách nào đó, vì không thể chỉnh sửa thông qua EF. Trông giống như một giải pháp tuyệt vời.

Có thể dễ dàng lưu các thủ tục được lưu trữ vào các chức năng trong EF.

Vấn đề là, bạn nên nhập một hàng mới và EF cập nhật đúng dữ liệu trong bộ nhớ cache, nhưng bộ nhớ cache không được cập nhật sau khi gọi thủ tục đã lưu. Vẫn cần một số chức năng cập nhật hoặc làm mới thủ công. Nếu không, cuộc gọi sau để nhận các đối tượng được sắp xếp theo SortIndex sẽ cho kết quả sai.

Ngoài ra, có thể đặt MergeOption = MergeOption.OverwriteChanges cho một số thực thể, khiến EF cập nhật dữ liệu từ DB tốt hơn một chút. Với điều này được thực hiện, nó có thể đọc lại đối tượng sau khi chèn nó hoặc gọi thủ tục lưu sẵn và nó sẽ được làm mới. Tuy nhiên, việc đọc một bộ sưu tập các đối tượng có số db.Section.OrderBy(o => o.SortIndex) sẽ vẫn trả về kết quả được lưu trong bộ nhớ cache với thứ tự sắp xếp sai.

Nếu có ai quan tâm, có thể để làm cho MergeOption mặc định để cái gì khác bằng cách thêm EF partial class và sau đó phương pháp phần OnContextCreated, như ở đây:

public partial class DatabaseEntities 
{ 
    partial void OnContextCreated() 
    { 
     Subsection.MergeOption = MergeOption.OverwriteChanges; 
     Section.MergeOption = MergeOption.OverwriteChanges; 
     Function.MergeOption = MergeOption.OverwriteChanges; 
    } 
} 
+0

Cảm ơn, nó hoạt động cho tôi !!! – Rodrigo

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