Unit of work là gì

Repository, hiểu một giải pháp dễ dàng, là một trong tầng phân chia giữa Data Access Layer (DAL) và Bussiness Logic Layer.

Bạn đang xem: Unit of work là gì

Unit of Work là 1 kỹ thuật nhằm đảm bảo toàn bộ các request tới database cơ mà tất cả tương quan tới nhau đông đảo được tiến hành bên trên cùng một DbContext

1. DbContext của Entity Framework Core2. Repository

1. DbContext của Entity Framework Core

“Trước tiếng xài mà lại có lưu ý DbContext là gì đâu” -> trên đây chắc hẳn rằng triệu chứng bình thường của kha khá technology liên quan tới .NET, lúc mà lại phần đa sản phẩm đã có xuất bản sẵn, với chúng ta chỉ gồm nhiệm vụ … xài

DbContext là 1 trong thực thể đại diện thay mặt cho một phiên thao tác với database, dùng để query với lưu tài liệu của bạn

Vì nó chỉ đại diện cho một phiên làm việc, vào ASP..NET, mỗi một khi có một request mới từ bỏ browser, 1 DbContext bắt đầu sẽ tiến hành tạo thành, với sẽ bị dispose lúc return response mang đến browser

Thông thường, bạn sẽ kế thừa lại trường đoản cú DbContext, nhét thêm những DbSet vào, trường đoản cú kia mới query các kiểu dáng được

quý khách có thể tham khảo thêm về cách thiết lập DbContext ở chỗ này, mục 3.2

1.1. DbContext Tracking

Để đảm bảo tính trọn vẹn tài liệu, DbContext cần sử dụng 1 hiệ tượng Call là tracking.

Lúc bạn đổi khác 1 record (thêm, xóa, sửa), thì đổi khác đó ko được đưa xuống database ngay, cơ mà đã còn vương vấn lại. DbContext đang theo dõi sự biến đổi này.

Xem thêm: Cách Bật Mở Bàn Phím Ảo Win 7 Trên Máy Tính, Laptop, Cách Mở Bàn Phím Ảo Trên Windows 7

Tính đến khi bạn sẽ thực hiện tất cả những biến đổi cần thiết, rồi Hotline yourDbContext.SaveChanges(), thì từ bây giờ, số đông thay đổi được traông xã sẽ được ship xuống database.

Vậy toàn bộ rất nhiều vấn đề này liên quan gì cho tới Repository với Unit of Work? DbContext là 1 trong implement của Repository với Unit of Work, chỉ tất cả điều nó ở sâu vào framework, còn implement của bạn sẽ nằm ở vị trí application

2. Repository

Có cái sơ vật giỏi ho sau

*

Bạn có thể tham khảo thêm về các services được inject trên nội dung bài viết Dependency Injection trong ASP.NET Core

Vậy đóa, Repository đóng vai trò là 1 lớp trung gian giữa Bussiness Logic Layer (controllers với services) cùng Data Access Layer (những DbContext)

2.1. Lý do

Tách việc giải pháp xử lý súc tích cùng câu hỏi truy vấn databaseDễ trace bugDễ unit testDễ đổi khác xúc tích hoặc databaseGom thông thường nhìu tác vụ cơ bản về 1 chỗKo đề nghị viết đi viết lại 1 tác vụ những lần

2.2. Implement

Cụ tỉ, Repository sẽ sở hữu các nhiệm vụ: Liệt kê list các record – Lấy 1 record – Thêm – Xóa – Sửa 1 record

Bài toán: làm chủ học sinh

Tạo interface

using System;using System.Collections.Generic;using ContosoUniversity.Models;namespace ContosoUniversity.DAL public interface IStudentRepository : IDisposable IEnumerable GetStudents(); Student GetStudentByID(int studentId); void InsertStudent(Student student); void DeleteStudent(int studentID); void UpdateStudent(Student student); void Save(); Đoạn code bên trên khai báo một cỗ CRUD (Create – Read – Update – Delete) gớm điển

Tạo class implement

using System;using System.Collections.Generic;using System.Linq;using System.Data;using ContosoUniversity.Models;namespace ContosoUniversity.DAL public class StudentRepository : IStudentRepository, IDisposable // SchoolContext thừa kế từ bỏ DbContext, và tất cả thêm DbSet private SchoolContext context; public StudentRepository(SchoolContext context) this.context = context; public IEnumerable GetStudents() return context.Students.ToList(); public Student GetStudentByID(int id) return context.Students.Find(id); public void InsertStudent(Student student) context.Students.Add(student); public void DeleteStudent(int studentID) Student student = context.Students.Find(studentID); context.Students.Remove(student); public void UpdateStudent(Student student) context.Entry(student).State = EntityState.Modified; public void Save() context.SaveChanges(); private bool disposed = false; protected virtual void Dispose(bool disposing) if (!this.disposed) if (disposing) context.Dispose(); this.disposed = true; public void Dispose() Dispose(true); GC.SuppressFinalize(this); Inject repository này vào Controller hoặc Service (ghi nhớ knhị báo nó vào Startup.cs trước nhóe)

public class StudentController private readonly IStudentRepository _studentRepository; public StudentController(IStudentRepository studentRepository) _studentRepository = studentRepository

2.3. Performance Hit

Entity Framework khi query một record hoặc 1 bộ record làm sao kia vào database, nó sẽ trả về dạng IQueryable. Chỉ lúc nào các bạn điện thoại tư vấn .ToList();, thì câu lệnh Squốc lộ mới được hiện ra và gửi tặng database.

Xem thêm: Who First Said "Long Time, No See" And In Which Language? : Code Switch : Npr

Trong StudentRepository ngơi nghỉ trên, giả dụ bạn có nhu cầu filter 1 list các student có tên là “ABC”, thì vẫn đề nghị code trong controller nlỗi sau

public IActionResult GetStudents(string name) // Squốc lộ đã được hình thành, toàn bộ student trong db đã có trả về và lưu giữ trong memory var allStudents = _studentRepository.GetStudents(); // filter này chỉ triển khai việc filter trên memory var filteredStudents = allStudents.Where(x => x.Name.Contains(name)); return View(filteredStudents);Đây là 1 trong code rất tệ Lúc mà student gồm hàng ngàn record, trong khi bạn chỉ cần 1 số không nhiều các record mà thôi.

Ở phần sau, các bạn sẽ biết phương pháp fix mang lại vụ việc này, đôi khi implement 1 generic repository cho những tác vụ CRUD cơ bản

3. Generic Repository

Về cơ bản, ta đang sử dụng kiểu dáng knhì báo generic class của C# để implement generic repository

using System;using System.Collections.Generic;using System.Linq;using System.Data;using System.Data.Entity;using ContosoUniversity.Models;using System.Linq.Expressions;namespace ContosoUniversity.DAL public class GenericRepository where TEntity : class // SchoolContext được kế thừa tự DbContext internal SchoolContext context; // Generic repository này đang vận động dựa trên entity được truyền vào Khi đăng ký trong Startup.cs internal DbSet dbSet; public GenericRepository(SchoolContext context) this.context = context; this.dbSet = context.Set(); // Expression> filter: có thể chấp nhận được các bạn truyền vào một filter expression dạng LINQ public virtual IEnumerable Get( Expression> filter = null, Func, IOrderedQueryable> orderBy = null, string includeProperties = "") IQueryable query = dbSet; // Query là 1 trong dạng IQueryable, chỉ được thực thi Lúc đề xuất cực hiếm danh sách if (filter != null) query = query.Where(filter); // Tiếp theo, nó sẽ dĩ nhiên các property quan trọng khi người dùng hướng dẫn và chỉ định foreach (var includeProperty in includeProperties.Split (new char<> ',' , StringSplitOptions.RemoveEmptyEntries)) query = query.Include(includeProperty); // Sau cùng, nó xúc tiến bằng phương pháp translate thành câu lệnh Squốc lộ với call xuống database if (orderBy != null) return orderBy(query).ToList(); else return query.ToList(); // vào asp.net, Id cho một object có thể là GUID hoặc int public virtual TEntity GetByID(object id) return dbSet.Find(id); public virtual void Insert(TEntity entity) dbSet.Add(entity); // trong asp.net, Id cho 1 object có thể là GUID hoặc int public virtual void Delete(object id) TEntity entityToDelete = dbSet.Find(id); Delete(entityToDelete); public virtual void Delete(TEntity entityToDelete) if (context.Entry(entityToDelete).State == EntityState.Detached) dbSet.Attach(entityToDelete); dbSet.Remove(entityToDelete); public virtual void Update(TEntity entityToUpdate) dbSet.Attach(entityToUpdate); context.Entry(entityToUpdate).State = EntityState.Modified; 4. Tạo class Unit of WorkUnit of Work chỉ có một trọng trách tuyệt nhất, bảo đảm an toàn toàn bộ các repository của bạn hồ hết dùng phổ biến một DbContext. Bằng cách này, lúc thực hiện ngừng toàn bộ các tác vụ chuyển đổi database, bạn chỉ việc Call DbContext.SaveChanges() 1 lần tốt nhất, với các đổi khác đó sẽ được bảo quản trong database

using System;using ContosoUniversity.Models;namespace ContosoUniversity.DAL public class UnitOfWork : IDisposable private SchoolContext context = new SchoolContext(); private GenericRepository departmentRepository; private GenericRepository courseRepository; // Kiểm tra coi repository đã làm được khởi tạo ra không public GenericRepository DepartmentRepository get if (this.departmentRepository == null) this.departmentRepository = new GenericRepository(context); return departmentRepository; // Kiểm tra coi repository đã có được khởi chế tác chưa public GenericRepository CourseRepository get if (this.courseRepository == null) this.courseRepository = new GenericRepository(context); return courseRepository; public void Save() context.SaveChanges(); private bool disposed = false; protected virtual void Dispose(bool disposing) if (!this.disposed) if (disposing) context.Dispose(); this.disposed = true; public void Dispose() Dispose(true); GC.SuppressFinalize(this); Bước tiếp sau là thay đổi code của controller nhằm thực hiện class UnitOfWork vừa new khởi tạo

// Lấy datavar courses = unitOfWork.CourseRepository.Get(includeProperties: "Department");// Lấy và order datavar departmentsQuery = unitOfWork.DepartmentRepository.Get(orderBy: q => q.OrderBy(d => d.Name));// Insertvar course = new Course();course.Name = "Test";...unitOfWork.CourseRepository.Insert(course);unitOfWork.Save();// HủyunitOfWork.Dispose();5. Tổng kếtVậy là chúng ta đang phát âm khái niệm và giải pháp knhị báo Repository và Unit of Work pattern. quý khách cũng đã biết phương pháp thực hiện lambda expression để query các data thỏa ĐK mong muốn thông qua interface IQueryable. Chúc vui