Trong .NET, tracking và non-tracking queries là những cách để tương tác với cơ sở dữ liệu.
Trong lập trình .NET, tracking là tính năng của Entity Framework Core (EF Core) để theo dõi trạng thái của các đối tượng trong cơ sở dữ liệu. Khi sử dụng tracking, EF Core sẽ theo dõi và lưu trữ các thay đổi của đối tượng trong bộ đệm thay đổi. Khi gọi phương thức SaveChanges(), các thay đổi này sẽ được lưu vào cơ sở dữ liệu.
Tracking được kích hoạt mặc định cho tất cả các truy vấn trong EF Core. Tuy nhiên, trong một số trường hợp, sử dụng tracking có thể làm giảm hiệu suất và tốn tài nguyên. Vì vậy, khi chỉ đọc dữ liệu từ cơ sở dữ liệu mà không cần lưu trữ thay đổi, ta nên sử dụng non-tracking query để cải thiện hiệu suất.
Để tắt tính năng tracking trong EF Core, ta có thể sử dụng phương thức AsNoTracking() hoặc AsTracking(false) trong truy vấn.
Tracking query là trạng thái mặc định của các câu truy vấn. Khi sử dụng tracking query, Entity Framework Core sẽ theo dõi thay đổi của đối tượng trong cơ sở dữ liệu và lưu trữ chúng trong bộ đệm thay đổi. Tracking query được sử dụng khi cần thay đổi trạng thái của cơ sở dữ liệu.
1. Non-tracking query được sử dụng cho các truy vấn chỉ để đọc dữ liệu. Non-tracking query cung cấp hiệu suất tốt hơn so với tracking query. Ví dụ: khi lấy danh sách sinh viên, bạn không cần phải lưu trữ thay đổi của chúng.
Giả sử chúng ta có một ứng dụng quản lý sinh viên. Khi muốn thay đổi thông tin của một sinh viên trong cơ sở dữ liệu, chúng ta sử dụng tracking query. Ví dụ:
using (var context = new StudentContext())
{
var student = context.Students.Find(1); // lấy thông tin sinh viên có ID là 1
student.Name = "New Name"; // thay đổi tên của sinh viên
context.SaveChanges(); // lưu thay đổi vào cơ sở dữ liệu
}
Trong ví dụ trên, chúng ta sử dụng tracking query để lấy thông tin của sinh viên và thay đổi tên của sinh viên đó. Sau đó, chúng ta sử dụng SaveChanges() để lưu thay đổi vào cơ sở dữ liệu.
2. Identity Resolution là tính năng của Entity Framework Core được sử dụng trong tracking query. Nó giúp định danh các đối tượng và trả về cùng một đối tượng nếu đối tượng đó đã được theo dõi. Tuy nhiên, nếu sử dụng non-tracking query, một đối tượng mới sẽ được trả về mỗi lần truy vấn được thực hiện.
Giả sử chúng ta có một ứng dụng hiển thị danh sách sinh viên. Khi muốn chỉ đọc thông tin sinh viên từ cơ sở dữ liệu mà không cần lưu trữ thay đổi, chúng ta sử dụng non-tracking query. Ví dụ:
using (var context = new StudentContext())
{
var students = context.Students.AsNoTracking().ToList(); // lấy danh sách sinh viên
foreach (var student in students)
{
Console.WriteLine(student.Name); // hiển thị tên sinh viên
}
}
Trong ví dụ trên, chúng ta sử dụng non-tracking query để lấy danh sách sinh viên từ cơ sở dữ liệu. Với AsNoTracking(), chúng ta chỉ đọc thông tin sinh viên mà không lưu trữ thay đổi. Sau đó, chúng ta hiển thị tên của từng sinh viên trong danh sách.
3. AsNoTrackingWithIdentityResolution là tính năng mới được thêm vào Entity Framework Core để kết hợp cả hai tính năng tracking và non-tracking. Nó sử dụng một bộ đệm thay đổi độc lập để định danh đối tượng mà không cần theo dõi kết quả trong context. Sau khi truy vấn được liệt kê, bộ đệm thay đổi được thu gom bởi garbage collector.
Giả sử chúng ta có một ứng dụng quản lý bán hàng, với hai bảng dữ liệu: Product (sản phẩm) và Order (đơn hàng). Mối quan hệ giữa hai bảng là một sản phẩm có thể có nhiều đơn hàng.
Khi muốn lấy danh sách sản phẩm và số lượng đơn hàng tương ứng, chúng ta sử dụng AsNoTrackingWithIdentityResolution để kết hợp cả hai tính năng tracking và non-tracking. Ví dụ:
using (var context = new SalesContext())
{
var products = context.Products
.Include(p => p.Orders)
.AsNoTrackingWithIdentityResolution()
.ToList(); // lấy danh sách sản phẩm và số lượng đơn hàng tương ứng
foreach (var product in products)
{
Console.WriteLine($"{product.Name} - {product.Orders.Count()}"); // hiển thị tên sản phẩm và số lượng đơn hàng
}
}
Trong ví dụ trên, chúng ta sử dụng AsNoTrackingWithIdentityResolution để lấy danh sách sản phẩm và số lượng đơn hàng tương ứng. Với .Include(p => p.Orders), chúng ta kết nối bảng Order với bảng Product để lấy số lượng đơn hàng tương ứng. Sau đó, chúng ta sử dụng AsNoTrackingWithIdentityResolution() để kết hợp cả hai tính năng tracking và non-tracking. Khi liệt kê danh sách sản phẩm, chúng ta hiển thị tên sản phẩm và số lượng đơn hàng tương ứng.