Tôi là pro-repository, mặc dù tôi đã chuyển khỏi các mẫu kho lưu trữ chung. Thay vào đó, tôi sắp xếp các kho lưu trữ của mình với chức năng kinh doanh mà chúng phục vụ. Các kho lưu trữ không nhằm mục đích trừu tượng hóa ORM, vì đây không phải là bất cứ điều gì tôi mong muốn thay đổi, đồng thời tôi tránh làm cho một kho lưu trữ quá chi tiết. (Tức là CRUD) Thay vào đó, kho của tôi phục vụ hai đến ba mục đích chính:
- Phục hồi dữ liệu
- Tạo dữ liệu
- Xóa cứng
Để lấy dữ liệu, kho lưu trữ luôn trả về IQueryable<TEntity>
. Để tạo dữ liệu, nó trả về TEntity. Kho lưu trữ xử lý bộ lọc cấp cơ sở của tôi, chẳng hạn như trạng thái "hoạt động" ủy quyền cho các hệ thống sử dụng các mẫu xóa mềm và trạng thái "hiện tại" cho các hệ thống sử dụng dữ liệu lịch sử. Việc tạo dữ liệu chỉ chịu trách nhiệm đảm bảo rằng các tham chiếu cần thiết được giải quyết và liên kết và thực thể được thiết lập và sẵn sàng hoạt động.
Cập nhật dữ liệu là trách nhiệm của logic nghiệp vụ làm việc với (các) thực thể được đề cập. Điều này có thể bao gồm những thứ như quy tắc xác nhận. Tôi không thử đóng gói nó trong một phương thức lưu trữ.
Xóa trong hầu hết các hệ thống của tôi là xóa mềm để nó được cập nhật dữ liệu. (IsActive = false) Trong trường hợp xóa cứng, đây sẽ là một lớp lót trong Kho lưu trữ.
Tại sao phải lưu trữ? Khả năng kiểm tra. Chắc chắn, DbContext có thể bị chế giễu, nhưng đơn giản hơn là giả định một lớp trả vềIQueryable<TEntity>
. Chúng cũng chơi tốt với mẫu UoW, cá nhân tôi sử dụng mẫu DbContextScope của Mehdime để tìm ra đơn vị công việc ở mức tôi muốn (Bộ điều khiển Ie trong MVC) và cho phép các bộ điều khiển và lớp dịch vụ trợ giúp của tôi sử dụng kho lưu trữ mà không cần phải chuyển tham chiếu đến UoW / dbContext xung quanh. Sử dụng IQueryable có nghĩa là bạn không cần nhiều phương thức trình bao bọc trong kho lưu trữ và mã của bạn có thể tối ưu hóa cách dữ liệu sẽ được tiêu thụ. Ví dụ, kho lưu trữ không cần hiển thị các phương thức như "Tồn tại" hoặc "Đếm" hoặc cố gắng bọc các thực thể với các POCO khác trong trường hợp bạn muốn có các bộ dữ liệu phụ. Họ thậm chí không cần xử lý các tùy chọn tải háo hức cho dữ liệu liên quan mà bạn có thể cần hoặc không cần. Bằng cách chuyển IQueryable, mã gọi có thể:
.Any()
.Count()
.Include() // Generally avoided, instead I use .Select()
.Where()
.Select(x => new ViewModel or Anon. Type)
.Skip().Take()
.FirstOrDefault() / .SingleOrDefault() / .ToList()
Rất linh hoạt và từ một PoV thử nghiệm, kho lưu trữ giả của tôi chỉ cần trả về Danh sách các đối tượng thực thể được điền.
Đối với các kho lưu trữ chung, phần lớn tôi đã chuyển khỏi các kho này bởi vì khi bạn kết thúc với một kho lưu trữ trên mỗi bảng, bộ điều khiển / dịch vụ của bạn kết thúc với các tham chiếu đến một số kho lưu trữ để thực hiện một hành động kinh doanh. Trong hầu hết các trường hợp, chỉ có một hoặc hai trong số các kho lưu trữ này thực sự đang thực hiện các thao tác ghi (với điều kiện bạn đang sử dụng các thuộc tính điều hướng đúng cách) trong khi phần còn lại hỗ trợ những người có Đọc. Tôi muốn có một cái gì đó giống như một Kho lưu trữ đơn hàng có khả năng đọc và tạo đơn hàng và đọc bất kỳ tra cứu có liên quan, v.v. (đối tượng khách hàng nhẹ, sản phẩm, v.v.) để tham khảo khi tạo đơn hàng, hơn là nhấn 5 hoặc 6 kho khác nhau. Nó có thể vi phạm những người theo chủ nghĩa thuần túy DNRY, nhưng lập luận của tôi cho rằng mục đích của kho lưu trữ là phục vụ việc tạo Đơn hàng bao gồm các tham chiếu liên quan.Repository<Product>
để có được các sản phẩm trong cơ sở của một đơn đặt hàng, tôi chỉ cần một thực thể với một số ít các lĩnh vực. Đơn hàng của tôi có thể có một .GetProducts()
phương thức trả về IQueryable<ProductSummary>
mà tôi thấy đẹp hơn phương thức Repository<Product>
mà cuối cùng có một số phương thức "Nhận" để thử và phục vụ các khu vực khác nhau của nhu cầu của ứng dụng và / hoặc một số biểu thức lọc thông qua phức tạp.
Tôi chọn mã đơn giản hơn để dễ theo dõi, kiểm tra và điều chỉnh. Nó có thể bị lạm dụng theo những cách xấu, nhưng tôi muốn có một cái gì đó mà sự lạm dụng dễ dàng phát hiện và sửa chữa hơn là cố gắng "khóa" mã theo cách không thể bị lạm dụng, thất bại, và sau đó có một cái gì đó một cơn ác mộng để thực sự làm những gì khách hàng trả tiền để có được nó cuối cùng. :)