Khi nào nên sử dụng mẫu kho lưu trữ


20

Tôi đã đọc gần đây rằng việc sử dụng mẫu kho lưu trữ kết hợp với ORM là không tốt. Theo hiểu biết của tôi, điều này là do sự trừu tượng mà họ cung cấp trên cơ sở dữ liệu SQL quá rò rỉ để được chứa trong mẫu.

Tôi có một vài câu hỏi về điều này:

  1. Bạn làm gì nếu bạn muốn tắt ORM? Bạn sẽ có mã cụ thể ORM trong ứng dụng của mình nếu bạn không chứa nó trong kho lưu trữ.

  2. Mẫu lưu trữ có còn hợp lệ khi không sử dụng ORM và bạn đang sử dụng ADO.NET để truy cập dữ liệu và tự điền dữ liệu đối tượng?

  3. Nếu bạn sử dụng ORM nhưng không phải mẫu lưu trữ, nơi bạn giữ các truy vấn thường được sử dụng? Sẽ là khôn ngoan khi biểu diễn mỗi truy vấn dưới dạng một lớp và có một số loại nhà máy truy vấn để tạo các thể hiện?


1
1) bạn sẽ không bao giờ có thể trao đổi ORM do các hành vi khác nhau của họ, ngay cả khi cả hai đều hỗ trợ linq, họ sẽ hành xử đủ khác nhau để ứng dụng của bạn bị hỏng. ví dụ: hành vi tải lười biếng, theo dõi bẩn, proxy ma, v.v. Tuy nhiên, thật tuyệt khi có thể trao đổi ORM để triển khai trong mem để thử nghiệm ..
Roger Johansson

Để biết giá trị của nó, tôi sẽ thảo luận về Kho lưu trữ / ORM tại đây: stackoverflow.com/questions/13180501/ Kẻ
Eric King

Nơi mà bạn đã đọc rằng đó là một thực hành xấu?
Dave Hillier

Câu trả lời:


3

1) Đúng, nhưng tần suất bạn tắt ORM là bao nhiêu?
2) Tôi sẽ nói như vậy, bởi vì bối cảnh ORM là một kho lưu trữ và ẩn giấu rất nhiều công việc liên quan đến việc tạo truy vấn, truy xuất dữ liệu, ánh xạ, v.v. Nếu bạn không sử dụng ORM, logic đó vẫn phải nằm ở đâu đó. Tôi không biết liệu điều đó có đủ điều kiện làm mẫu kho lưu trữ theo nghĩa chặt chẽ nhất của từ này không ...
3) Truy vấn đóng gói là thứ tôi thấy thường xuyên, nhưng thường là nhiều hơn cho mục đích kiểm tra / khai thác. Ngoài ra, tôi sẽ cẩn thận khi sử dụng lại một truy vấn trên các phần khác nhau của ứng dụng, bởi vì sau đó bạn có nguy cơ tạo ra sự phụ thuộc vào thứ gì đó có thể thay đổi n lần (n là số nơi bạn sử dụng truy vấn).


1
1) Bạn đang hỏi sai câu hỏi. Nó không quan trọng thường xuyên, nó chỉ phải là một lần. Với số lượng tùy chọn ORM có sẵn, có thể có một tùy chọn tốt hơn so với những gì bạn đang sử dụng. Câu hỏi bây giờ trở thành: điều gì xảy ra khi bạn làm gì? Kho lưu trữ cung cấp cho bạn một sự trừu tượng tốt đẹp. Tôi đã ở đó và tôi ước tôi có một sự trừu tượng như vậy ngay từ đầu.
ngớ ngẩn

3
@devnull Tôi không đồng ý. Nếu nó sẽ xảy ra nhiều nhất một lần, tôi sẽ coi đó là một rủi ro chấp nhận được. Nếu bạn sợ lựa chọn sai: hãy thử nghiệm nhiều hơn trước khi cam kết. Về lý thuyết, một sự trừu tượng như vậy nghe có vẻ hay, nhưng trong thực tế, bạn kết thúc việc tái tạo một phần khá lớn trong api của ORM của bạn, tất cả chỉ vì bạn có thể sẽ chọn một nơi khác vào một ngày nào đó, ở đâu đó. Đối với tôi, đó là sự lãng phí công sức, mã dự phòng và nhiều mã hơn mà chính bạn phải duy trì và đảm bảo. Ngoài ra, chuyển đổi ORM không nên ảnh hưởng đến toàn bộ ứng dụng; tìm hiểu để đặt ranh giới tên miền.
Stefan Billiet

Thay đổi ORM không phải là lý do duy nhất cho kho lưu trữ. Nếu bạn cần giới thiệu bộ đệm [phân tán] trong ứng dụng của mình - tất cả các thay đổi sẽ được thực hiện trong kho lưu trữ và BL của bạn sẽ không thay đổi do thay đổi của lớp truy cập dữ liệu.
Valery

trong hầu hết các trường hợp, bộ đệm phân tán sẽ được tích hợp vào ORM?
dùng1450877

Tôi nghĩ rằng nó phụ thuộc vào ORM. Bạn có thể quyết định sử dụng ORM nhẹ hơn NHibernate hoặc EF.
Valery

2

1) Bạn sẽ làm gì nếu bạn muốn tắt ORM, bạn sẽ có mã ORM cụ thể trong ứng dụng của mình nếu bạn không chứa nó trong kho lưu trữ.

Tôi chưa ở vị trí mà công ty đột nhiên quyết định chuyển đổi công nghệ truy cập dữ liệu. Nếu điều này xảy ra, một số công việc sẽ được yêu cầu. Tôi có xu hướng hoạt động truy cập dữ liệu trừu tượng thông qua các giao diện. Kho lưu trữ là một cách để giải quyết điều này.

Sau đó tôi sẽ có một hội đồng khác để thực hiện cụ thể lớp truy cập dữ liệu của mình. Ví dụ: tôi có thể có:

Company.Product.DataCompany.Product.Data.EntityFrameworklắp ráp. Việc lắp ráp đầu tiên sẽ được sử dụng hoàn toàn cho các giao diện, khi khác sẽ là triển khai cụ thể logic truy cập dữ liệu của Entity Framework.

2) Mẫu kho lưu trữ có còn hợp lệ khi không sử dụng ORM và bạn đang sử dụng ADO.net để truy cập dữ liệu và tự điền dữ liệu đối tượng?

Tôi nghĩ rằng tùy thuộc vào bạn để quyết định mẫu nào hợp lệ hay không. Tôi đã sử dụng một mẫu kho lưu trữ trong lớp trình bày. Một điều cần lưu ý là mọi người thích ném trách nhiệm vào kho lưu trữ. Trước khi bạn biết điều đó, lớp kho lưu trữ của bạn sẽ nhảy múa, hát và làm tất cả mọi thứ. Bạn muốn tránh điều này.

Tôi đã thấy một lớp kho lưu trữ bắt đầu bằng cách có các trách nhiệm GetAll, GetById, Cập nhật và Xóa, điều này là tốt. Vào thời điểm dự án hoàn thành, cùng một lớp có hàng tá phương thức (trách nhiệm) đáng lẽ không bao giờ có ở đó. Ví dụ: GetByForename, GetBySurname, UpdateWithExinating và tất cả các loại công cụ điên rồ.

Đây là nơi các truy vấn và lệnh phát huy tác dụng.

3) Nếu bạn sử dụng ORM nhưng không phải mẫu lưu trữ, nơi bạn giữ các truy vấn thường được sử dụng. Sẽ là khôn ngoan khi biểu diễn mỗi truy vấn dưới dạng một lớp và có một số loại nhà máy truy vấn để tạo các thể hiện?

Tôi nghĩ rằng đó là một ý tưởng rất tốt để sử dụng các truy vấn và lệnh thay vì kho lưu trữ. Tôi làm như sau:

  • Xác định giao diện cho một truy vấn. Điều này sẽ giúp bạn kiểm tra đơn vị. Ví dụpublic interface IGetProductsByCategoryQuery { ... }

  • Xác định thực hiện cụ thể cho một truy vấn. Bạn sẽ có thể tiêm những thứ này thông qua khung IoC mà bạn chọn. Ví dụpublic class GetProductsByCategoryQuery : IGetProductsByCategoryQuery

Bây giờ thay vì gây ô nhiễm kho lưu trữ với hàng tá trách nhiệm, tôi chỉ cần nhóm các truy vấn của mình thành các không gian tên. Ví dụ: giao diện cho truy vấn trên có thể tồn tại: Company.SolutionName.Products.Queriesvà việc triển khai có thể ởCompany.SolutionName.Products.Queries.Implementation

Khi nói đến việc cập nhật hoặc xóa dữ liệu, tôi sử dụng mẫu lệnh theo cách tương tự.

Một số có thể không đồng ý và nói rằng trước khi dự án hoàn thành, bạn sẽ có hàng tá các lớp và không gian tên. Vâng, bạn sẽ làm vậy. Trong tâm trí tôi, đó là một điều tốt khi bạn có thể duyệt qua giải pháp trong IDE mà bạn chọn và ngay lập tức xem loại trách nhiệm nào mà thành phần nhất định có. Nếu bạn đã quyết định sử dụng một mẫu kho lưu trữ thay thế, bạn sẽ phải xem xét bên trong mỗi lớp kho lưu trữ để cố gắng thực hiện các trách nhiệm của nó.


Tôi thích ý tưởng có các lệnh thay vì các hàm chung. Tôi có thể đọc thêm về cách triển khai chúng trong bối cảnh truy cập dữ liệu ở đâu?
ankush981

1

TUYÊN BỐ TỪ CHỐI: Những gì tiếp theo dựa trên sự hiểu biết và kinh nghiệm ngắn gọn của tôi về mẫu đã nói (Kho lưu trữ đó là). Tôi có thể đang làm sai ... thực tế, tôi khá tích cực rằng tôi đang làm sai :). Vì vậy, trong khi đây là một nỗ lực cho một câu trả lời, nó cũng là một câu hỏi ngụy trang.

Tôi đang sử dụng mẫu Kho lưu trữ để trừu tượng hóa lớp truy cập dữ liệu, trong hầu hết các trường hợp là ORM. Nó là một giao diện chung, với các phương thức cho các lớp Tạo, Đọc, Cập nhật, Xóa và triển khai cho LINQ to SQL và EF cho đến nay. Tôi có thể thực hiện ghi vào các tệp XML trên đĩa (chỉ là một ví dụ hoang dã về những gì tôi có thể làm với nó). Tôi không triển khai Đơn vị công việc vì được ORM hỗ trợ. Nếu cần, tôi có thể thực hiện nó. Tôi thích nó theo cách này bởi vì, cho đến nay, nó đã cho tôi một sự tách biệt tốt đẹp. Tôi không nói rằng không có lựa chọn thay thế tốt hơn.

Để trả lời câu hỏi của bạn:

  1. Cho dù bạn có muốn hay không, thay đổi sẽ xảy ra. Và nếu bạn đã viết một loạt các ứng dụng và thời gian đã đến để duy trì chúng, nhưng cảm thấy đó là một nỗi đau khi làm việc với ORM hiện tại và muốn thay đổi nó, bạn sẽ tự khen mình vì đã làm cho một sự trừu tượng như vậy. Chỉ cần sử dụng bất cứ thứ gì bạn cảm thấy thoải mái, có thể là Kho lưu trữ hoặc mẫu / khái niệm khác.
  2. Có, miễn là bạn sử dụng nó để phân tách truy cập dữ liệu. Giống như tôi đã đề cập trước đó, bạn có thể thực hiện ghi dữ liệu trong các tệp phẳng.
  3. Tôi sử dụng Kho lưu trữ để giữ các truy vấn và Đối tượng truy vấn thường sử dụng của mình khi tôi có các truy vấn mà tôi muốn điều chỉnh (không có nhiều).

Để cho bạn một ví dụ khác, những kẻ ở Umbraco đã trừu tượng hóa container DI, chỉ trong trường hợp họ có thể muốn chuyển sang thứ khác.


0

Nếu ORM cung cấp tính linh hoạt của LINQ, tải háo hức, v.v. Tôi sẽ không giấu nó đằng sau bất kỳ lớp bổ sung nào.
Nếu nó liên quan đến sql thô (micro ORM) thì nên sử dụng "phương thức cho mỗi truy vấn" để đạt được khả năng sử dụng lại, do đó làm cho mẫu kho lưu trữ phù hợp.

What do you do if you want to switch out ORMs? 
You would have ORM specific code in your application if you do not contain it in a repository.

Tại sao bạn cần phải chuyển đổi?
Một trong đó có hầu hết các tính năng bạn cần nên được sử dụng. Có thể bản phát hành mới của ormX mang đến các tính năng mới và hóa ra tốt hơn bản hiện tại, nhưng ...
Nếu bạn chọn ẩn orm, bạn chỉ có thể sử dụng các tính năng mà tất cả các ứng cử viên có.
Ví dụ: bạn không thể sử dụng Dictionary<string, Entity>các thuộc tính trong các thực thể của mình vì ormY không thể xử lý chúng.

Giả sử LINQ được sử dụng, phần lớn chuyển đổi orm chỉ là chuyển đổi các tham chiếu thư viện và thay thế session.Query<Foo>()bằng context.Fooshoặc tương tự cho đến khi nó biên dịch. Nhiệm vụ nhàm chán, nhưng mất ít thời gian hơn so với mã hóa lớp trừu tượng.

Is the repository pattern still valid when not using an ORM and you are using ADO.NET for data access and populating object data yourself?

Vâng. Mã phải được tái sử dụng và điều đó có nghĩa là đặt tòa nhà sql, vật chất hóa đối tượng, vv ở một nơi (lớp riêng biệt). Bạn cũng có thể gọi lớp "XRep repository" và trích xuất một giao diện từ nó.

If you use an ORM but not the repository pattern where do you keep commonly used queries? 
Would it be wise to represent each query as a class and have some sort of query factory to create instances?

Giả sử LINQ được sử dụng, một lớp bao bọc sẽ quá mức IMHO. Một cách đẹp hơn sẽ là phương pháp mở rộng

public static IQueryable<T> Published<T>(this IQueryable<T> source) where T : Page
{
    // at some point someone is going to forget to check that status
    // so it makes sense to extract this thing
    return source.Where(x => x.Status == Status.Published && x.PublishTime <= DateTime.UtcNow);
}

Bất kỳ mã nào được sử dụng ở nhiều nơi (hoặc có tiềm năng) và đủ phức tạp (dễ bị lỗi), nên được trích xuất đến một nơi tập trung.

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.