2011-12-28 30 views
5

Như một kịch bản rất thô sơ, chúng ta hãy hai hoạt động sau đây:dài sống Entity Framework bối cảnh - thực hành tốt nhất để tránh toàn vẹn dữ liệu phát hành

UserManager.UpdateFirstName(int userId, string firstName) 
{ 
    User user = userRepository.GetById(userId); 
    user.FirstName = firstName; 
    userRepository.SaveChanges(); 
} 

InventoryManager.InsertOrder(Order newOrder) 
{ 
    orderRepository.Add(newOrder); 
    orderRepository.SaveChanges(); 
} 

Tôi chỉ có sử dụng EF trong các dự án web và phụ thuộc nhiều vào bản chất không quốc tịch của web. Với mọi yêu cầu, tôi sẽ nhận được một bản sao mới của bối cảnh được chèn vào các đối tượng mặt tiền lớp kinh doanh của tôi (dịch vụ, người quản lý, bất kỳ thứ gì bạn muốn gọi cho họ), tất cả các nhà quản lý kinh doanh chia sẻ cùng một ngữ cảnh của EF. Hiện tại tôi đang làm việc trên một dự án WPF và tôi đang tiêm các nhà quản lý kinh doanh và sau đó là các kho lưu trữ mà họ sử dụng trực tiếp vào Mô hình Xem.

Giả sử người dùng đang ở trên màn hình phức tạp và lần nhấp nút đầu tiên của họ gọi phương thức UpdateFirstName(). Giả sử SaveChanges() không thành công vì bất kỳ lý do gì. Nhấn nút thứ hai của họ sẽ gọi phương thức InsertOrder().

Trên web, đây không phải là vấn đề vì bối cảnh hoạt động # 2 không liên quan (yêu cầu http mới) đến ngữ cảnh được sử dụng bởi thao táC# 1. Trên máy tính để bàn tuy nhiên, đó là bối cảnh tương tự trên cả hai hành động. Vấn đề phát sinh trong thực tế là tên đầu tiên của người dùng đã được sửa đổi và như vậy được theo dõi bởi bối cảnh. Mặc dù SaveChanges() ban đầu không có (nói db không có sẵn tại thời điểm đó), thao tác thứ hai gọi SaveChanges() sẽ không chỉ chèn thứ tự mới, nó cũng sẽ cập nhật tên người dùng đầu tiên. Chỉ là về mọi nguyên nhân, điều này không được mong muốn, vì người dùng từ lâu đã quên mất hành động đầu tiên của họ. Điều này rõ ràng là một ví dụ ngớ ngẩn, nhưng tôi luôn có xu hướng gặp phải những tình huống như thế này, tôi ước rằng tôi có thể bắt đầu mới với bối cảnh mới cho mọi hành động của người dùng trái ngược với cuộc sống lâu dài hơn (cho cuộc đời của cửa sổ WPF chẳng hạn).

Các bạn xử lý các tình huống này như thế nào?

Trả lời

3

Sự thẩm vấn rất thực tế khi đến từ các ứng dụng dành cho máy tính để bàn đặc biệt trực tiếp truy cập vào cơ sở dữ liệu.

Câu trả lời dường như đi cùng với triết lý cho ORM là có ngữ cảnh có tuổi thọ tương tự như màn hình của bạn. Ngữ cảnh dữ liệu là thực thi Đơn vị công việc, về bản chất. Đối với một ứng dụng web, nó rõ ràng là yêu cầu và nó hoạt động tốt.

Đối với ứng dụng dành cho máy tính để bàn, bạn có thể có ngữ cảnh gắn với màn hình hoặc có thể liên quan đến hoạt động chỉnh sửa (giữa tải và nhấn "lưu"). Thao tác chỉ đọc có thể có ngữ cảnh throwaway (sử dụng ID để tải lại đối tượng khi cần thiết, ví dụ khi nhấn "nút xóa" trong lưới). Hãy quên đi một bối cảnh kéo dài toàn bộ cuộc sống của ứng dụng nếu bạn muốn nhận thức được những sửa đổi từ những người dùng khác (bộ sưu tập mối quan hệ được lưu trong bộ nhớ cache khi được tải lần đầu tiên). Cũng quên chia sẻ trực tiếp các thực thể EF giữa các cửa sổ khác nhau, bởi vì điều đó có hiệu quả làm cho nó trở thành ngữ cảnh được ứng dụng rộng rãi và lâu dài.

Dường như với tôi, ORM có xu hướng thực thi thiết kế giống như trên web trên ứng dụng dành cho máy tính để bàn vì điều này. Không có cách nào thực sự xung quanh điều này tôi sợ. Không phải là điều cần thiết. Bạn thường không nên tấn công cơ sở dữ liệu ở cấp độ máy tính để bàn nếu nó được chia sẻ giữa nhiều phiên bản. Trong trường hợp đó bạn sẽ sử dụng một lớp dịch vụ, EF sẽ ở trong phần tử của nó và vấn đề của bạn sẽ được chuyển sang "ngữ cảnh dịch vụ" ...

+1

Dennis, trên thực tế câu hỏi của tôi là về một ngữ cảnh cho mỗi cửa sổ, tôi thậm chí không cân nhắc chia sẻ nó trên bất cứ điều gì nhiều hơn thế. Tôi chỉ đơn giản là tự hỏi về "nhà nước" mà bối cảnh duy trì cho cuộc sống của cửa sổ. Nhiều cửa sổ có các hoạt động không liên quan, một số có thể bị lỗi, một số khác chúng tôi chỉ muốn từ bỏ (sau khi sửa đổi một số thực thể được theo dõi bởi ngữ cảnh, nhưng không gọi Savechang). Nó cảm thấy đúng với tôi để duy trì một bối cảnh cho mỗi cửa sổ cách tiếp cận, tôi chỉ không thấy làm thế nào nó thực sự có thể làm việc cho tôi mà không gây ra vấn đề toàn vẹn dữ liệu vô tận. – e36M3

+0

Được rồi, đọc lại câu hỏi gốc của bạn và bình luận của bạn, EF có một số cách để đối phó với thất bại và dọn dẹp, bằng cách làm mới các thực thể (với các tùy chọn khác nhau về những người chiến thắng liên quan đến sửa đổi địa phương). –

+0

Thực tế là nó có Denis, tuy nhiên trừ khi bạn đang chơi trực tiếp với bối cảnh trong View Model của bạn trái ngược với việc trải qua một tầng kinh doanh chứa một kho chung chứa ngữ cảnh EF, nó gần như không thể sử dụng các tính năng như vậy. Tôi đoán tôi đã hy vọng có nhiều ý kiến ​​về kinh nghiệm hơn. Tôi chắc rằng tôi không phải là người duy nhất không đi qua các dịch vụ WCF đến cơ sở dữ liệu. – e36M3

2

Chúng tôi có một ứng dụng WPF lớn gọi các dịch vụ WCF để thực hiện các hoạt động CRUD như 'UpdateFirstName()' hoặc 'InsertOrder()'.Mọi cuộc gọi vào dịch vụ tạo ra một ObjectContext mới, do đó chúng ta không cần phải lo lắng về ObjectContexts không nhất quán treo xung quanh.

Vứt bỏ ObjectContext ngay khi bạn hoàn thành nó. Không có gì sai khi tạo một ObjectContext mới khi đang di chuyển. Có chi phí đáng kể trong việc tạo ra một ObjectContext mới và bạn sẽ tiết kiệm cho mình nhiều lỗi và đau đầu trong tương lai.

Giả sử bạn tạo một ObjectContext mới mỗi khi một phương thức được gọi trên kho lưu trữ của bạn, đoạn mã dưới đây sẽ vẫn cung cấp cho bạn hỗ trợ giao dịch bằng cách sử dụng lớp TransactionScope. Ví dụ:

 using (TransactionScope scope = new TransactionScope()) 
     { 
      UserManager.UpdateFirstName(userid,firstName); 
      InventoryManager.InsertOrder(newOrder); 

      scope.Complete(); 
     } 
+0

Chris Tôi tránh một tầng WCF đúng như tôi không thấy nó cần thiết cho ứng dụng cụ thể này. Điều đó nói rằng tôi rõ ràng có thể tái tạo cùng một hành vi mà không có các dịch vụ ngắt kết nối thực sự (trong lớp bộ nhớ có thể hoạt động giống nhau). Những gì bạn làm trong một tình huống mà bạn muốn có một "hoạt động kinh doanh/giao dịch" để mở rộng nhiều dịch vụ và một cam kết/rollback ở cuối? Vẻ đẹp của cách tiếp cận của tôi là tất cả các nhà quản lý tầng kinh doanh của tôi (dịch vụ nếu bạn muốn) chia sẻ cùng một bối cảnh dữ liệu bên dưới, do đó tôi có thể đơn vị công việc tiện ích phát hành một cuộc gọi SaveChanges() ở cuối. – e36M3

+0

Trong trường hợp của chúng tôi, chúng tôi có thể thiết lập một vài thuộc tính trên các lớp dịch vụ WCF của chúng tôi và chúng tôi tự động nhận hỗ trợ giao dịch trên nhiều dịch vụ và máy. WCF đã được thực hiện cho loại điều này. Trong trường hợp của bạn, bạn có kho lưu trữ của bạn trong quá trình, vì vậy bạn có thể bọc các cuộc gọi kho của bạn trong một TransactionScope. Tôi đã chỉnh sửa câu trả lời của mình để minh họa ý tôi. – ChrisNel52

+0

Thú vị, tôi cho rằng câu hỏi tiếp theo của tôi không liên quan đến bản gốc nhưng thật tuyệt khi biết WCF có tính năng này được tích hợp sẵn. – e36M3

0

Một cách hoàn toàn khác là viết tất cả thay đổi trực tiếp vào cơ sở dữ liệu (với bối cảnh cơ sở dữ liệu ngắn ngủi). Và sau đó thêm một số loại dự thảo/phiên bản trên đó. Bằng cách đó bạn vẫn có thể cung cấp chức năng ok/undo/cancel.

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