0

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();

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

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí