- vừa được xem lúc

Mẫu thiết kế Generic và Non-Generic Repository trong C#

0 0 17

Người đăng: Phương Khang

Theo Viblo Asia

Mẫu thiết kế repository được sử dụng để tạo ra một lớp abstract giữa lớp DAL và lớp BL để thực hiện các thao tác CRUD (Create, Read, Update, Delete) đối với cơ sở dữ liệu bên dưới. Chúng ta cũng đã thảo luận rằng mẫu thiết kế repository có thể được thực hiện theo hai cách sau đây.

Generic Repository Pattern

Mẫu generic Repository được sử dụng để định nghĩa các thao tác như CRUD cho tất cả các thực thể CSDL trong một lớp duy nhất.

Non-Generic Repository Pattern (Specific Repository)

Mẫu Non-Generric Repository được sử dụng để định nghĩa tất cả các thao tác cơ sở dữ liệu liên quan đến một thực thể cụ thể trong một lớp riêng biệt. Ví dụ, nếu bạn có hai thực thể là Nhân viên (Employee) và Khách hàng (Customer), thì mỗi thực thể sẽ có lớp repository đặc thù riêng của nó để thực hiện các thao tác cơ sở dữ liệu đối với thực thể đó. Trước khi triển khai cả các Generic Repository và Non-Generic Repository, chúng ta cần phải hiểu rõ cách triển khai. Điều này có nghĩa là khi nào thì nên sử dụng generic repository, khi nào thì nên sử dụng non-generic repository và khi nào thì nên sử dụng cả generic repository và non-generic repository trong cùng một ứng dụng. Trong bài viết này, mình sẽ thảo luận về Mẫu Thiết kế Repository trong C# với một ví dụ sử dụng Entity Framework Core và ứng dụng ASP.NET MVC. Mẫu Thiết kế Repository trong C# là một trong những mẫu thiết kế được sử dụng nhiều nhất trong ứng dụng thời gian thực. Tại cuối bài viết này, bạn sẽ hiểu những điểm chính của Generic Repository.

Cách triển khai mẫu Repository

Nếu bạn sử dụng một trong các triển khai trên, thì với cách triển khai generic repository, bạn không thể sử dụng các thao tác cụ thể cho một thực thể và trong trường hợp triển khai non-generic repository, bạn phải viết code cho các thao tác CRUD chung cho mỗi thực thể, nghĩa là với mỗi mỗi 1 class Customer, Employee bạn phải khai báo thao tác CRUD cho nó những 2 lần và với cách triển khai generic repository thì bạn chỉ cần khai báo thao tác CRUD 1 lần duy nhất. Vì vậy, cách tốt hơn là chỉ tạo một generic repository cho các thao tác CRUD thường được sử dụng và cho thao tác cụ thể, tạo một non-generic và kế thừa từ generic repository. Sơ đồ dưới đây giải thích những điều trên.

Hiểu rõ hơn về Generic Repository, Non-Generic Repository thông qua một ví dụ cụ thể.

Sửa đổi tập tin IGenericRepository.cs như được hiển thị bên dưới.

namespace RepositoryUsingEFinMVC.GenericRepository
{ public interface IGenericRepository<T> where T : class { IEnumerable<T> GetAll(); T GetById(object id); void Insert(T obj); void Update(T obj); void Delete(object id); void Save(); }
}

Thay đổi file GenericRepository.cs như bên dưới

namespace RepositoryUsingEFinMVC.GenericRepository
{ public class GenericRepository<T> : IGenericRepository<T> where T : class { public EmployeeDBContext _context = null; public DbSet<T> table = null; public GenericRepository() { this._context = new EmployeeDBContext(); table = _context.Set<T>(); } public GenericRepository(EmployeeDBContext _context) { this._context = _context; table = _context.Set<T>(); } public IEnumerable<T> GetAll() { return table.ToList(); } public T GetById(object id) { return table.Find(id); } public void Insert(T obj) { table.Add(obj); } public void Update(T obj) { table.Attach(obj); _context.Entry(obj).State = EntityState.Modified; } public void Delete(object id) { T existing = table.Find(id); table.Remove(existing); } public void Save() { _context.SaveChanges(); } }
}

Lưu ý: Đoạn mã trên là khai báo của Generic Repository, trong đó chúng ta khai báo thao tác chung CRUD chung cho mỗi thực thể.

Bây giờ chúng ta cần khai báo cụ thể cho mỗi thực thể. Hãy giả sử chúng ta muốn thêm hai thao tác bổ sung cho thực thể Employee như lấy Danh sách Nhân viên theo giới tính và lấy Danh sách Nhân viên theo bộ phận. Vì hai thao tác này thêm cho thực thể Employee nên không có nghĩa là khai báo 2 thao tác này vào Generic Repository

Vì vậy, chúng ta cần tạo một Repository không phải là generic có tên là EmployeeRepository, nó sẽ kế thừa từ GenericRepository. Trong Repository này, chúng ta cần cung cấp hai thao tác cụ thể như được hiển thị bên dưới.

Thay đổi file IEmployeeRepository.cs như bên dưới

using RepositoryUsingEFinMVC.DAL;
using RepositoryUsingEFinMVC.GenericRepository;
using System.Collections.Generic;
namespace RepositoryUsingEFinMVC.Repository
{ public interface IEmployeeRepository : IGenericRepository<Employee> { IEnumerable<Employee> GetEmployeesByGender(string Gender); IEnumerable<Employee> GetEmployeesByDepartment(string Dept); }
}

Thay đổi file EmployeeRepository.cs như bên dưới

namespace RepositoryUsingEFinMVC.Repository { public class EmployeeRepository : GenericRepository<Employee>, IEmployeeRepository { public IEnumerable<Employee> GetEmployeesByGender(string Gender) { return _context.Employees.Where(emp => emp.Gender == Gender).ToList(); } public IEnumerable<Employee> GetEmployeesByDepartment(string Dept) { return _context.Employees.Where(emp => emp.Dept == Dept).ToList(); } } }

Bây giờ chúng ta cần sử dụng cả Generic Repository và Non-Generic Repository trong Employee Controller.

Thay đổi file Employee Controller như bên dưới

using RepositoryUsingEFinMVC.Repository;
using System.Web.Mvc;
using RepositoryUsingEFinMVC.DAL;
using RepositoryUsingEFinMVC.GenericRepository;
namespace RepositoryUsingEFinMVC.Controllers
{ public class EmployeeController : Controller { private IGenericRepository<Employee> repository = null; private IEmployeeRepository employee_repository = null; public EmployeeController() { this.employee_repository = new EmployeeRepository(); this.repository = new GenericRepository<Employee>(); } public EmployeeController(EmployeeRepository repository) { this.employee_repository = repository; } public EmployeeController(IGenericRepository<Employee> repository) { this.repository = repository; } [HttpGet] public ActionResult Index() { //you can not access the below two mwthods using generic repository //var model = repository.GetEmployeesByDepartment("IT"); var model = employee_repository.GetEmployeesByGender("Male"); return View(model); } [HttpGet] public ActionResult AddEmployee() { return View(); } [HttpPost] public ActionResult AddEmployee(Employee model) { if (ModelState.IsValid) { repository.Insert(model); repository.Save(); return RedirectToAction("Index", "Employee"); } return View(); } [HttpGet] public ActionResult EditEmployee(int EmployeeId) { Employee model = repository.GetById(EmployeeId); return View(model); } [HttpPost] public ActionResult EditEmployee(Employee model) { if (ModelState.IsValid) { repository.Update(model); repository.Save(); return RedirectToAction("Index", "Employee"); } else { return View(model); } } [HttpGet] public ActionResult DeleteEmployee(int EmployeeId) { Employee model = repository.GetById(EmployeeId); return View(model); } [HttpPost] public ActionResult Delete(int EmployeeID) { repository.Delete(EmployeeID); repository.Save(); return RedirectToAction("Index", "Employee"); } }
}

Chú ý: Bằng cách sử dụng một Non-Generic Repository, chúng ta có thể truy cập tất cả các thao tác. Nhưng bằng cách sử dụng Generic-Repository, chúng ta chỉ có thể truy cập các thao tác được định nghĩa trong kho chứa thông thường.

**Nguồn: **https://dotnettutorials.net/lesson/repository-pattern-implementation-guidelines-csharp/

Bình luận

Bài viết tương tự

- vừa được xem lúc

Tổng hợp các bài hướng dẫn về Design Pattern - 23 mẫu cơ bản của GoF

Link bài viết gốc: https://gpcoder.com/4164-gioi-thieu-design-patterns/. Design Patterns là gì. Design Patterns không phải là ngôn ngữ cụ thể nào cả.

0 0 270

- vừa được xem lúc

Giới thiệu về Builder Design Pattern

Nguồn: refactoring.guru. Builder. Ý đồ.

0 0 33

- vừa được xem lúc

Một ví dụ nhỏ về Factory method

Trong bài viết trước mình đã giới thiệu tới các bạn về Abstract Factory pattern, các bạn quan tâm có thể theo dõi lại tại đây. Để tiếp tục về chủ đề design pattern trong bài viết này mình sẽ trình bày những khái niệm, ưu nhược điểm và các sử dụng của một creational design pattern khác đó là Factory

0 0 27

- vừa được xem lúc

Tôi đã dùng Service Pattern trong NuxtJS như thế nào ?

Giới thiệu. Trong quá trình làm VueJS NuxtJS hay thậm chí là Laravel mình cũng hay áp dụng các pattern như Service hoặc Repository.

0 0 58

- vừa được xem lúc

Hướng dẫn Adapter Design Pattern

Trong bài viết này, chúng ta sẽ cùng tìm hiểu về Adapter Design Pattern qua cấu trúc, cánh triển khai, ví dụ, ưu điểm nhược điểm và ứng dụng của nó. Đây là bài viết đầu tiên của mình nên sẽ không trán

1 1 52

- vừa được xem lúc

Giới thiệu về Prototype Design Pattern

Ý đồ. Prototype là một creational design pattern cho phép bạn sao chép các object hiện có mà không làm cho code của bạn phụ thuộc vào các class của chúng.

0 0 43