Giới thiệu
Trong lập trình, giá trị object (value object) là một khái niệm quan trọng giúp chúng ta tổ chức dữ liệu một cách hiệu quả. Một giá trị object là một đối tượng có thể được xác định bởi thành phần của các giá trị của nó. Ví dụ, một địa chỉ có thể được xem như một giá trị object vì sự kết hợp của quốc gia/khu vực, thành phố, và đường phố xác định nó. Trong bài viết này, chúng ta sẽ tìm hiểu chi tiết về giá trị object, cách lưu trữ chúng trong Entity Framework Core (EF Core) và một số thực hành tốt nhất.
Đặc điểm quan trọng của giá trị object
-
Không có danh tính (Identity): Giá trị object không có danh tính riêng. Ví dụ, hai khách hàng có cùng tên không thể được phân biệt bằng tên mà phải dựa vào ID của họ. Ngược lại, nếu hai địa chỉ giống hệt nhau, chúng được coi là giống nhau.
-
Bất biến (Immutable): Giá trị của một giá trị object phải bất biến ngay khi đối tượng được tạo ra. Khi đối tượng được tạo ra, bạn cần cung cấp các giá trị cần thiết nhưng không cho phép chúng thay đổi.
Tình huống thực tế
Hãy xem xét một root tổng hợp đơn hàng (Order aggregate root). Root tổng hợp này chứa một thực thể có tên là Order Item với một ID, vì hai mục đơn hàng có sản phẩm giống nhau vẫn được coi là khác nhau. Ngược lại, một giá trị object như địa chỉ sẽ được coi là giống nhau nếu hai địa chỉ có cùng các giá trị.
Ví dụ thực tế
Giả sử bạn có một đơn hàng với nhiều mục và mỗi mục đều có một giá trị object là địa chỉ giao hàng. Địa chỉ này sẽ được lưu trữ dưới dạng một giá trị object trong EF Core.
Cách triển khai giá trị object trong C#
Bạn có thể tạo một lớp cơ sở cho giá trị object có các phương thức tiện ích cơ bản như so sánh dựa trên tất cả các thuộc tính và các đặc điểm cơ bản khác. Mỗi giá trị object sẽ kế thừa từ lớp cơ sở này.
Ví dụ mã C#:
csharp
public abstract class ValueObject
{
// Phương thức so sánh
public override bool Equals(object obj)
{
// So sánh các thuộc tính
}
// Phương thức lấy hash
public override int GetHashCode()
{
// Tính toán hash
}
}
public class Address : ValueObject
{
public string Street { get; private set; }
public string City { get; private set; }
public string Country { get; private set; }
public Address(string street, string city, string country)
{
Street = street;
City = city;
Country = country;
}
}
Cách lưu trữ giá trị object trong cơ sở dữ liệu
Sử dụng loại thực thể sở hữu (Owned Entity Type)
Cách tốt nhất để lưu trữ giá trị object với EF Core 2.0 và các phiên bản sau là sử dụng loại thực thể sở hữu. Một loại thực thể sở hữu cho phép bạn ánh xạ các loại không có danh tính. Để triển khai giá trị object, thực thể nên chứa điều hướng đến giá trị object và trong file cấu hình, loại thực thể sở hữu nên được định nghĩa.
Ví dụ trong thực thể Order:
Trong thực thể Order, địa chỉ là một giá trị object và nó được triển khai như một loại thực thể sở hữu trong thực thể chủ sở hữu.
csharp
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Order>()
.OwnsOne(o => o.Address);
}
Theo mặc định, quy ước của EF Core sẽ đặt tên các cột cho các thuộc tính của loại thực thể sở hữu theo kiểu EntityProperty_OwnedEntityProperty
. Do đó, các thuộc tính của địa chỉ sẽ xuất hiện trong bảng Orders với tên là Address_Street
, Address_City
, nhưng bạn có thể tùy chỉnh với Property().HasColumnName()
.
Thực hành tốt nhất
- Định nghĩa rõ ràng: Đảm bảo rằng các giá trị object của bạn được định nghĩa rõ ràng và dễ hiểu.
- Bất biến: Luôn đảm bảo rằng các giá trị object của bạn là bất biến sau khi được tạo ra.
- Sử dụng loại thực thể sở hữu: Khi lưu trữ, hãy sử dụng loại thực thể sở hữu để dễ dàng quản lý các giá trị object.
Những cạm bẫy thường gặp
- Không hiểu rõ giá trị object: Nhiều lập trình viên nhầm lẫn giữa thực thể và giá trị object. Hãy nhớ rằng giá trị object không có danh tính.
- Thay đổi giá trị: Cần tránh việc thay đổi giá trị của một giá trị object sau khi nó được tạo ra.
Mẹo hiệu suất
- Tối ưu hóa truy vấn: Khi làm việc với giá trị object, hãy đảm bảo rằng các truy vấn của bạn được tối ưu hóa để tránh mất hiệu suất.
- Sử dụng lazy loading: Cân nhắc sử dụng lazy loading cho các giá trị object để cải thiện hiệu suất.
Xử lý sự cố
- Lỗi ánh xạ: Nếu bạn gặp lỗi ánh xạ, hãy kiểm tra cấu hình của loại thực thể sở hữu trong file cấu hình của EF Core.
- Dữ liệu không chính xác: Nếu dữ liệu không chính xác được lưu trữ, hãy xem lại các phương thức khởi tạo của giá trị object.
Kết luận
Giá trị object là một phần quan trọng trong thiết kế hệ thống. Chúng giúp chúng ta tổ chức dữ liệu một cách hiệu quả và rõ ràng hơn. Qua bài viết này, bạn đã hiểu rõ hơn về khái niệm giá trị object, cách triển khai và lưu trữ chúng trong EF Core. Hãy áp dụng những kiến thức này vào dự án của bạn để cải thiện chất lượng mã nguồn.
Câu hỏi thường gặp (FAQ)
1. Giá trị object khác gì so với thực thể?
Giá trị object không có danh tính, trong khi thực thể có danh tính riêng và có thể thay đổi.
2. Làm thế nào để đảm bảo rằng giá trị object là bất biến?
Bạn nên không cung cấp các phương thức thay đổi trong lớp giá trị object của mình.
3. Có thể sử dụng giá trị object trong các ngôn ngữ lập trình khác không?
Có, khái niệm giá trị object có thể áp dụng trong nhiều ngôn ngữ lập trình hiện đại.