Design pattern: Unit Of Work Pattern

Chúng tôi rất vui mừng chia sẻ kiến thức sâu sắc về từ khóa Unit of work la gi để tối ưu hóa nội dung trang web và tiếp thị trực tuyến. Bài viết cung cấp phương pháp tìm kiếm, phân tích từ khóa và chiến lược hiệu quả. Cảm ơn sự quan tâm và hãy tiếp tục theo dõi để cập nhật kiến thức mới.

Đây là phần thứ hai trong series ứng dụng Design pattern vào trong dự án .NET. Như trong phần 1, tất cả chúng ta đã tìm hiểu qua Repository pattern là gì và hoạt động ra sao. Trong phần này tất cả chúng ta sẽ mở rộng một tí từ Repository pattern và ứng dụng mô hình Unit Of Work vào thử xem nó cải thiện được những gì nhé.

Bạn Đang Xem: Design pattern: Unit Of Work Pattern

Trong mô hình Repository Pattern rất dễ để nhận ra tất cả chúng ta có nhiều hơn một repository, chắng hẳn như ví dụ trong phần 1 tất cả chúng ta có 3 repository (CustomerRepository, OrderRepository và ProductRepository). Nếu 3 thằng này hoạt động riêng biệt tức là chỉnh sửa tài liệu mỗi thằng không tác động ảnh hưởng đến thằng kia thì tất cả chúng ta không nói đến nhưng trong trường hợp này Order và Customer có quan hệ với nhau. Khi tất cả chúng ta thêm một Order thì trước tiên mình sẽ check list Customer có hay là không? nếu có thì tất cả chúng ta sẽ lấy Customer đó từ CustomerRepository còn không thì tất cả chúng ta sẽ phải tạo 1 instance mới.

public IActionResult Create(CreateOrderModel model) { if (!model.LineItems.Any()) return BadRequest(“Please submit line items”); if (string.IsNullOrWhiteSpace(model.Customer.Name)) return BadRequest(“Customer needs a name”); var customer = CustomerRepository.Find(c => c.Name == model.Customer.Name).FirstOrDefault(); if (customer != null) { customer.ShippingAddress = model.Customer.ShippingAddress; customer.PostalCode = model.Customer.PostalCode; customer.City = model.Customer.City; customer.Country = model.Customer.Country; customerRepository.Update(customer); customerRepository.SaveChanges(); } else { customer = new Customer { Name = model.Customer.Name, ShippingAddress = model.Customer.ShippingAddress, City = model.Customer.City, PostalCode = model.Customer.PostalCode, Country = model.Customer.Country }; } var order = new Order { LineItems = model.LineItems .Select(line => new LineItem { ProductId = line.ProductId, Quantity = line.Quantity }) .ToList(), Customer = customer }; orderRepository.Add(order); orderRepository.SaveChanges(); return Ok(“Order Created”); }

Xem Thêm : Bia Hơi Là Gì? Mọi Thứ Bạn Cần Biết Về Bia Hơi

Như ví dụ trên trong cùng một hàm mà tất cả chúng ta phải gọi database đến tận 4 lận, thực chất cả hai customerRepository và orderRepository đều là dbContext trong EntityFramework nhưng mà là 2 instance khác biệt nhau dẫn đến phải gọi database nhiều lần cho việc update của mỗi thằng. Do vậy để nâng cao hiểu quả thì vì sao không tạo 1 lớp chứa tất cả những thằng này khi thay đổi gì đó thì update 1 lần mà thôi 👍

Trước nhất tất cả chúng ta cần tạo 1 lớp UnitOfWork là nơi chứa tất cả repository tất cả chúng ta có. Lớp này mình viết trong tầng Infrastructure cùng với tụi repository

public interface IUnitOfWork { IRepositoryvàlt;Customervàgt; CustomerRepository { get; } IRepositoryvàlt;Ordervàgt; OrderRepository { get; } IRepositoryvàlt;Productvàgt; ProductRepository { get; } void SaveChanges(); } public class UnitOfWork : IUnitOfWork { private ShoppingContext context; public UnitOfWork(ShoppingContext context) { this.context = context; } private IRepositoryvàlt;Customervàgt; customerRepository; public IRepositoryvàlt;Customervàgt; CustomerRepository { get { if (customerRepository == null) { customerRepository = new CustomerRepository(context); } return customerRepository; } } private IRepositoryvàlt;Ordervàgt; orderRepository; public IRepositoryvàlt;Ordervàgt; OrderRepository { get { if(orderRepository == null) { orderRepository = new OrderRepository(context); } return orderRepository; } } private IRepositoryvàlt;Productvàgt; productRepository; public IRepositoryvàlt;Productvàgt; ProductRepository { get { if (productRepository == null) { productRepository = new ProductRepository(context); } return productRepository; } } public void SaveChanges() { context.SaveChanges(); } }

Lớp IUnitOfWork là interface gồm có các repository, bằng phương pháp này thay vì phải inject từng repository vào nơi cần sử dụng thì chỉ việc inject lớp UnitOfWork này và mỗi một khi cần được sử dụng thì nó mới khởi tạo instance cho repository đó. Như đã nói chỉ khi nào được gọi thì tất cả chúng ta mới tạo instance cho nó và có thêm một hàm SaveChange, khi gọi hàm này thì nhất loạt sẽ update tất cả Repository, hàm này được cung cấp bởi Enity Framework nha các bạn khỏi thắc mắc sao làm được 😉

Xem Thêm : Đầu tư ròng kí hiệu là gì? (Cập nhật 2022) – Luật ACC

Sau lúc đã tạo lớp UnitOfWork tất cả chúng ta inject nó vào nơi cần sử dụng, ví dụ trong OrderController hay vì phải inject nhiều instance repository thì chỉ việc inject lớp này thôi là có thể sử sụng được tất cả repository rồi.

//private readonly IRepositoryvàlt;Ordervàgt; orderRepository; //private readonly IRepositoryvàlt;Productvàgt; productRepository; //public OrderController(IRepositoryvàlt;Ordervàgt; orderRepository, // IRepositoryvàlt;Productvàgt; productRepository) //{ // this.orderRepository = orderRepository; // this.productRepository = productRepository; //} private readonly IUnitOfWork unitOfWork; public OrderController(IUnitOfWork unitOfWork) { this.unitOfWork = unitOfWork; }

Và sử dụng nó cũng rất đơn giản chỉ việc thêm tiền tố unitOfWork vào trước các hàm lúc đầu và sử dụng thôi không cần chỉnh sửa gì thêm 😉

public IActionResult Index() { var orders = unitOfWork.OrderRepository.Find(order => order.OrderDate > DateTime.UtcNow.AddDays(-1)); return View(orders); } public IActionResult Create() { var products = unitOfWork.ProductRepository.All(); return View(products); } [HttpPost] public IActionResult Create(CreateOrderModel model) { if (!model.LineItems.Any()) return BadRequest(“Please submit line items”); if (string.IsNullOrWhiteSpace(model.Customer.Name)) return BadRequest(“Customer needs a name”); var customer = unitOfWork.CustomerRepository .Find(c => c.Name == model.Customer.Name) .FirstOrDefault(); if(customer != null) { customer.ShippingAddress = model.Customer.ShippingAddress; customer.PostalCode = model.Customer.PostalCode; customer.City = model.Customer.City; customer.Country = model.Customer.Country; unitOfWork.CustomerRepository.Update(customer); } else { customer = new Customer { Name = model.Customer.Name, ShippingAddress = model.Customer.ShippingAddress, City = model.Customer.City, PostalCode = model.Customer.PostalCode, Country = model.Customer.Country }; } var order = new Order { LineItems = model.LineItems .Select(line => new LineItem { ProductId = line.ProductId, Quantity = line.Quantity }) .ToList(), Customer = customer }; unitOfWork.OrderRepository.Add(order); unitOfWork.SaveChanges(); return Ok(“Order Created”); }

So sánh hàm Create trong OrderController hiện tại với lúc đầu thì tất cả chúng ta thấy được số lần gọi đến database giảm đi đáng kể, đây là lợi ích của việc ứng dụng Unit Of Work Pattern trong dự án. Phần cuối cùng trong series này nói về Lazy Load Pattern, cảm ơn các bạn đã quan tâm 😘

  • https://github.com/quocthinh861/DesignPattern-UnitOfWork

You May Also Like

About the Author: v1000