Bạn có thể tạo một đối tượng DataContext của Entity và loại bỏ nó trong một khối sử dụng trong mỗi phương thức CRUD của tôi không?


10

Tôi đang xây dựng một ứng dụng wpf thực hiện các tính năng sau:

  1. Lấy dữ liệu người dùng nhập và đọc dữ liệu từ cơ sở dữ liệu
  2. thực hiện một số tính toán trên đó
  3. Hiển thị nó cho người dùng theo nhiều kiểu xem và viết các thay đổi trở lại db

Kiến trúc được đề xuất: Cơ sở dữ liệu -> Khung thực thể -> Kho lưu trữ -> Logic nghiệp vụ -> Dịch vụ dữ liệu -> ViewModel

Lý do sử dụng kiến ​​trúc này: Nhiều kịch bản có trong ứng dụng (Nhiều chế độ xem) và nhiều cơ sở dữ liệu. Do đó, tôi sẵn sàng sử dụng kho lưu trữ ở giữa để trừu tượng hóa.

Một cảnh báo là bối cảnh sẽ tồn tại lâu nếu kho được triển khai. Để khắc phục điều này, có ổn không khi tạo một bối cảnh và loại bỏ chúng trong một khối sử dụng () trong mỗi phương thức thô.

cảm thấy tự do để đề xuất phương pháp thay thế.


Có một cái nhìn vào chủ đề này tương tự như truy vấn của bạn. stackoverflow.com/questions/21875816/
trộm

Câu trả lời:


16

Sử dụng một đối tượng DbContext cho mỗi lần truy cập hoặc giao dịch dữ liệu.

DbContextlà một vật nhẹ; nó được thiết kế để được sử dụng một lần cho mỗi giao dịch kinh doanh. Tạo DbContextmột Singleton của bạn và sử dụng lại nó trong suốt ứng dụng có thể gây ra các vấn đề khác, như vấn đề rò rỉ đồng thời và rò rỉ bộ nhớ.

DbContextvề cơ bản thực hiện một Đơn vị công việc. Đối xử với nó cho phù hợp.

Đừng loại bỏ các đối tượng DbContext.

Mặc dù các DbContextdụng cụ IDisposable, bạn không nên vứt bỏ nó theo cách thủ công, bạn cũng không nên gói nó trong một usingtuyên bố. DbContextquản lý suốt đời của chính nó; khi yêu cầu truy cập dữ liệu của bạn hoàn tất, DbContextsẽ tự động đóng kết nối cơ sở dữ liệu cho bạn.

Để hiểu lý do tại sao, hãy xem xét điều gì xảy ra khi bạn chạy câu lệnh Linq trên bộ sưu tập thực thể từ a DbContext. Nếu bạn quay trở lại một nạp lười biếng IQueryabletừ phương pháp truy cập dữ liệu của bạn, bạn đứng lên một đường ống được không được thực thi cho đến khi khách hàng buộc một số dữ liệu từ nó (bằng cách gọi FirstOrDefault(), ToList()hoặc lặp lại trên nó).

Đọc thêm
Tôi có luôn phải gọi Dispose () trên các đối tượng DbContext của mình không?
Tại sao bạn không nên sử dụng Singleton DataContexts trong Entity Framework
Trở lại IEnumerable<T>so với IQueryable<T>
kho lưu trữ có nên trả về IQueryablekhông?


4
Mặc dù tôi chắc chắn rằng ai đó sẽ đưa ra một trường hợp đặc biệt nào đó cho việc này, nhưng thật lòng tôi không thể đưa ra một trường hợp sử dụng tốt để trả về một IQueryable không được vật chất hóa từ các lớp truy cập dữ liệu của bạn. Điều đó chỉ mang lại cho mã cuộc gọi khả năng tiếp cận dữ liệu của bạn (điều mà có lẽ nó không có hoạt động kinh doanh nào) và làm hỏng mọi thứ. Điều đó đang được nói, nó thực sự là một mối quan tâm lớn để lo lắng về việc sử dụng usingcác khối? Hay tôi chỉ không nghĩ đến một số trường hợp sử dụng IQueryable như bạn đề xuất sẽ gây rắc rối?
Becuzz

@Becuzz: DbContextChịu trách nhiệm quản lý suốt đời của chính nó. Đề nghị của tôi là để cho nó làm điều đó; nó sẽ hoạt động cho dù bạn đang sử dụng IQueryablehay IEnumerable. Trường hợp sử dụng rõ ràng nhất mà tôi có thể nghĩ đến cho việc tải lười biếng là nơi bạn trả lại một số đối tượng ViewModel với một bộ sưu tập liên quan trong đó, nhưng bộ sưu tập không bao giờ được sử dụng (hoặc chỉ được sử dụng một phần). IQueryablecho phép bạn tránh chi phí lấy các hồ sơ không sử dụng.
Robert Harvey

3
Tôi hiểu tất cả những điều đó, chỉ là tôi đã bị đốt cháy khi có người trả lại IQueryables ở mọi nơi. Và sau đó, một cái gì đó xa hơn chuỗi đã thêm một số bao gồm hoặc những thứ khác được thực hiện cho một truy vấn tồi tệ khủng khiếp (từ quan điểm hiệu suất DB). Và đó là một lỗi thú vị để theo dõi. Như vậy, tôi đã có cơ hội suy nghĩ về việc trả lại IQueryable có phải là một ý tưởng hay không. Và tôi không bao giờ có thể nghĩ về một thời điểm đáng giá cho sự cố bảo trì. (tt)
Becuzz

4
@RobertHarvey chính xác điểm của lớp kho lưu trữ là gì nếu nó trả về một IQueryable cho máy khách? Về cơ bản, bạn đang cung cấp cho khách hàng tùy chọn để viết các truy vấn - chắc chắn chúng sẽ không phải là các truy vấn sql nhưng dù sao chúng là các truy vấn (chỉ được viết bằng C #) và nó sẽ xuất hiện ở mọi nơi. Nếu một kho lưu trữ đang trả về IQueryable thì bạn cũng có thể vứt bỏ kho lưu trữ đó.
CodingYoshi

8
@RobertHarvey Tôi không đồng ý với việc không xử lý DbContext và không đồng ý với bài viết được đề cập. Toàn bộ ý tưởng là mã hóa giao diện và giao diện cho tôi biết đó là IDis Dùng một lần. Tôi sẽ không viết mã của mình dựa trên hoạt động bên trong về cách nhóm EF đã triển khai DbContext hoặc đuổi theo các nhà phát triển trong nhóm đó - họ có thể thay đổi bất cứ lúc nào họ muốn. Tôi cũng sẽ không yêu cầu bản thân hoặc các nhà phát triển khác bắt đầu đào sâu vào hoạt động bên trong của mỗi lớp để xem IDis Dùng có thực sự hữu ích hay không. Tôi đã làm việc quá chăm chỉ để khiến các nhà phát triển trong đội của mình xử lý chỉ để yêu cầu họ không phải lúc nào cũng vậy.
CodingYoshi

-3

Lý tưởng nhất là bối cảnh nên được khởi tạo và chấm dứt cho một giao dịch. Trong trường hợp của bạn, bối cảnh sẽ được khởi tạo trong Logic nghiệp vụ và được chuyển đến Kho lưu trữ để đọc / ghi dữ liệu.


2
Có, bởi vì logic nghiệp vụ có thể được duy trì nhiều hơn khi được kết hợp chặt chẽ với truy cập dữ liệu ... :(
TheCatWhisperer

-3

Nếu bạn gọi DbContext trên mỗi phương thức trong ứng dụng của mình, bạn sẽ gặp phải tình trạng rò rỉ bộ nhớ. Sử dụng một thể hiện duy nhất của DbContext. Xem bình luận trong ví dụ dưới đây:

public bool IsInStock(int _ProductId)
{
  var result = false;

  try
  {
    using (var dataService = new StoreDbDataService()) // NB: This line on each method will eventually cause memory leak.
    {
      result = dataService.IsInStock(_ProductId);
    }
  }
  catch (Exception ex)
  {
    Log.LogException(ex);
  }

  return result;
}

1
Bạn có thể giải thích tại sao gọi DbContext sẽ gây rò rỉ bộ nhớ không? Nhận xét trong nguồn không giúp tôi hiểu nó. Tôi sẽ giả định rằng khối sử dụng sẽ khiến cho Dispose được gọi trên StoreDBDataService, cuối cùng sẽ dọn sạch tất cả các tài nguyên được phân bổ, phải không?
Kasper van den Berg

Về cơ bản, đây là clip "cho phép" của Ron Swanson nhưng bằng mã.
Dagroom
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.