Tôi hiện đang làm việc thông qua một số trong những thách thức tương tự. Tôi không thực sự là fan của việc thêm Id vào lớp cơ sở ValueObject<T>
vì điều này cho phép một đối tượng Giá trị cho tất cả các giá trị đối tượng có cần hay không, cộng với một đối tượng giá trị theo định nghĩa không có Id. còn là một đối tượng giá trị theo nghĩa thuần túy.
Trước khi tiếp tục, tôi sẽ lưu ý rằng khái niệm then chốt trong mã hóa DDD là bạn không phải là DDD thuần túy ở khắp mọi nơi, miễn là bạn biết những nhượng bộ của bạn và thương mại của họ. Điều đó đang được nói, cách tiếp cận của bạn chắc chắn có thể được coi là tốt, tuy nhiên tôi tin rằng nó thêm một nhượng bộ có thể không thực sự cần thiết. Chủ yếu, điều này ảnh hưởng đến sự bình đẳng của các đối tượng giá trị của bạn. Với việc bổ sung Id, hai Thẻ, ngay cả với cùng một tên không còn bằng nhau.
Đây là cách tiếp cận của tôi cho tình huống này: Đầu tiên là dễ dàng, không thực sự áp dụng cho những gì tôi nghĩ rằng vấn đề của bạn là quan trọng. Đây là đối tượng giá trị duy nhất trong phần đầu tiên của câu trả lời của Martin.
- Biến đối tượng giá trị thành thuộc tính của thực thể.
Miễn là đối tượng giá trị của bạn chỉ bao gồm các thuộc tính kiểu đơn giản, Entity Framework sẽ ánh xạ điều này tốt.
Ví dụ:
public class BlogEntry : Entity<Guid>
{
public String Text { get; private set; }
public Tag Tag { get; private set; }
// Constructors, Factories, Methods, etc
}
Entity Framework sẽ xử lý mà chỉ là tốt, những gì bạn sẽ kết thúc với một BlogEntry bảng duy nhất mà bao gồm đơn giản của: Id
Bây giờ tôi hình dung rằng đó không thực sự là những gì sau này trong trường hợp này, nhưng đối với nhiều đối tượng giá trị nó hoạt động tốt. Một trong những tôi sử dụng thường xuyên là một đối tượng giá trị DateRange trong đó bao gồm một số tài sản. Sau đó, trên các đối tượng miền của tôi, tôi chỉ đơn giản là có một thuộc tính của Type DateRange. EF ánh xạ bản đồ vào bảng cho chính đối tượng miền.
Tôi mang lại điều này vì quay trở lại nhượng bộ mà chúng tôi đã thêm Id vào loại cơ sở ValueObject<T>
, mặc dù Id có thể không được liệt kê trong việc triển khai cụ thể đối tượng miền của bạn, nó vẫn ở đó và sẽ vẫn được chọn bởi Entity Framework cho điều này, có lẽ trường hợp sử dụng đối tượng giá trị phổ biến nhất không còn hoạt động tốt như thế nào nữa.
OK, cuối cùng, vào trường hợp cụ thể của bạn (mà tôi cũng đã chạy vào một vài lần). Đây là cách tôi đã chọn để xử lý sự cần thiết của một thực thể để chứa danh sách các đối tượng giá trị. Về cơ bản, nó tóm tắt để mở rộng sự hiểu biết của chúng ta về miền. Giả sử đối tượng giá trị Thẻ là để ghi lại Thẻ trong bài đăng trên blog, cách tôi xem xét đó là một BlogPost chứa danh sách thẻ PostTag với giá trị của Thẻ. Vâng, đó là một lớp nữa, nhưng bạn không cần phải thêm nó cho mọi đối tượng giá trị, nó chỉ cần thiết khi bạn có một danh sách các đối tượng giá trị, và tôi nghĩ tốt hơn thể hiện những gì đang xảy ra.
Vì vậy, đây là một ví dụ của việc thêm một danh sách của một đối tượng giá trị cho một thực thể (sử dụng đối tượng giá trị của mình trong Tag trên):
public class BlogEntry : Entity<Guid>
{
public String Text { get; private set; }
public ICollection<PostTag> PostTags { get; private set; }
// Constructors:
private BlogEntry(Guid id) : base(id) { }
protected BlogEntry() : this(Guid.NewGuid()) { }
// Factories:
public static BlogEntry Create (String text, ICollection<PostTag> tags = null)
{
if(tags == null) { tags = new List<PostTag>(); }
return new BlogEntry(){ Text = text, Tags = tags };
}
// Methods:
public void AddTag(String name)
{
PostTags.Add(PostTag.Create(name));
}
}
public class PostTag : Entity<Guid>
{
// Properties:
public Tag Tag { get; private set; }
public DateTime DateAdded { get; private set; } // Properties that aren't relevant to the value of Tag.
// Constructors:
private PostTag(Guid id) : base(id) { }
protected PostTag() : this(Guid.NewGuid()) { }
// Factories:
public static PostTag Create(Tag tag)
{
return new PostTag(){ Tag = tag, DateAdded = DateTime.Now };
}
public static PostTag Create(Tag tag, DateTime dateAdded)
{
return new PostTag(){ Tag = tag, DateAdded = dateAdded };
}
}
Điều đó sẽ cho phép BlogEntry của bạn để chứa nhiều thẻ mà không ảnh hưởng vật giá trị và Entity Framework sẽ ánh xạ nó tốt mà không cần phải làm gì đặc biệt.
Bạn có thể kế thừa lớp và thêm thuộc tính khóa vào lớp dẫn xuất –
Tôi nghĩ về điều đó, nhưng tôi vẫn sẽ kết thúc với 2 lớp cho mỗi đối tượng giá trị. –