Cách Sử Dụng Global Query Filters Trong EF Core
Trong bài viết này, mình sẽ hướng dẫn bạn cách loại bỏ các điều kiện
lặp lại trong các truy vấn cơ sở dữ liệu EF Core.
Vậy những truy vấn nào thuộc dạng này?
Một ví dụ điển hình là khi bạn triển khai soft-delete, và phải kiểm
tra xem bản ghi có bị xóa mềm hay chưa trong mọi truy vấn.
Hoặc khi bạn đang làm việc trong hệ thống multi-tenant, bạn cần chỉ
định tenantId trong mọi truy vấn.
May mắn thay, EF Core có một tính năng mạnh mẽ giúp bạn loại bỏ sự
lặp lại này đó chính là Query
Filters.
Hãy cùng xem cách triển khai chúng.
Cách Áp Dụng Query Filters
Trước khi giới thiệu về Query Filters, hãy xem cách thông thường mà
chúng ta vẫn làm.
Giả sử bạn có một bảng Orders hỗ trợ tính năng soft-delete, và bạn
không bao giờ muốn truy vấn ra các bản ghi đã bị xóa mềm.
Bắt đầu với entity Order có thuộc tính IsDeleted:
public class Order
{
public int Id { get; set; }
public bool IsDeleted { get; set; }
}
Và bạn có yêu cầu nghiệp vụ rằng chỉ được lấy những đơn hàng chưa bị
xóa.
Truy vấn EF có thể trông như sau:
dbContext
.Orders
.Where(order => !order.IsDeleted)
.Where(order => order.Id == orderId)
.FirstOrDefault();
Cách này hoạt động tốt, nhưng bạn phải nhớ áp dụng điều kiện này ở mọi
nơi có truy vấn đến Order. Để đơn giản hóa, ta có thể định nghĩa Query Filter cho entity
Order để EF tự động thêm điều kiện này vào mọi truy vấn.
Trong phương thức OnModelCreating của DbContext, bạn thêm đoạn sau:
modelBuilder
.Entity<Order>()
.HasQueryFilter(order => !order.IsDeleted);
Giờ bạn có thể bỏ phần kiểm tra soft-delete trong câu truy vấn:
dbContext
.Orders
.Where(order => order.Id == orderId)
.FirstOrDefault();
Và EF Core sẽ tự động sinh ra câu SQL như sau:
SELECT o.*
FROM Orders o
WHERE o.IsDeleted = FALSE AND o.Id = @orderId
Tắt Query Filters
Trong một số tình huống, bạn có thể muốn tạm thời vô hiệu hóa Query
Filters cho một truy vấn cụ thể.
Cách thực hiện rất đơn giản: gọi phương thức IgnoreQueryFilters()
trong truy vấn LINQ.
dbContext
.Orders
.IgnoreQueryFilters()
.Where(order => order.Id == orderId)
.FirstOrDefault();
Hãy cẩn thận khi dùng cách này, vì nó có thể dễ dàng dẫn đến những hành vi không mong muốn trong ứng dụng.
Một Số Lưu Ý Khi Dùng Query Filters
Dưới đây là vài điều bạn nên biết trước khi sử dụng Query Filters, giúp tránh lỗi trong quá trình phát triển.
1. Cấu hình nhiều Query Filters
Nếu bạn cấu hình nhiều Query Filters cho cùng một entity, chỉ
filter cuối cùng sẽ được áp dụng. Nếu bạn cần nhiều điều kiện, hãy kết hợp bằng toán tử logic &&.
2. Bỏ qua một phần Query Filter
Nếu bạn chỉ muốn bỏ qua một phần điều kiện trong Query Filter, điều
này không thể thực hiện được. Mỗi entity chỉ có thể có một Query Filter duy nhất.
Một cách xử lý là sử dụng IgnoreQueryFilters() để vô hiệu hóa toàn
bộ filter, sau đó tự thêm điều kiện mong muốn trong truy vấn cụ thể.
Với cách này, bạn có thể giảm thiểu đáng kể sự trùng lặp trong truy vấn, giúp mã nguồn gọn gàng và dễ bảo trì hơn.
All rights reserved