2015-05-23 18 views
15

Làm cách nào để duy trì các đối tượng có giá trị lâu dài trong Khung thực thể mà không gây ô nhiễm mô hình miền của tôi? EF (tốt, DBS quan hệ nói chung) yêu cầu tôi xác định một chìa khóa - mà đối tượng giá trị của tôi không có ra khỏi hộp, ví dụLàm thế nào để đối phó với các đối tượng giá trị trong khung Entity?

public class Tag : ValueObject<Tag> 
{ 
    private readonly string name; 

    public Tag(string name) 
    { 
     this.name = name; 
    } 

    public string Name { get { return this.name; }} 
} 

Mặt khác, tôi không nên giải quyết mối quan tâm kiên trì trong mô hình. Tôi có thực sự phải tạo một lớp khác bao gồm tất cả các trường từ đối tượng giá trị cộng với thuộc tính khóa và sau đó ánh xạ chúng với nhau không? Tôi không muốn.

Có thể có giải pháp thanh lịch hơn không?

+2

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 –

+0

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ị. –

Trả lời

9

Vaughn Vernon viết về các đối tượng giá trị bền vững (trang 248) trong cuốn sách xuất sắc của mình Implementing Domain-Driven Design.

ORM và giá trị đơn Objects

Ý tưởng cơ bản là để lưu trữ từng thuộc tính của giá trị trong các cột riêng biệt của hàng nơi Entity mẹ của nó được lưu trữ. Nói cách khác, một đối tượng Value duy nhất được denormalized thành hàng của thực thể cha của nó. Có lợi thế để sử dụng quy ước cho đặt tên cột để nhận dạng rõ ràng và chuẩn hóa cách thức các đối tượng được tuần tự hóa được đặt tên.

ORM và nhiều giá trị hỗ trợ bởi một thực thể cơ sở dữ liệu

Một cách tiếp cận rất đơn giản để kiên trì một tập hợp các trường hợp giá trị sử dụng một ORM và một cơ sở dữ liệu quan hệ được để điều trị các loại giá trị gia tăng như một thực thể trong mô hình dữ liệu. (...) Để thực hiện điều này, chúng tôi có thể sử dụng Layer Supertype.

mẫu giáp bối cảnh trong C# có thể được tìm thấy ở đây: https://github.com/VaughnVernon/IDDD_Samples_NET

+1

Vâng, đó là những gì tôi đã làm. ValueObject bây giờ có một phím số nguyên và do đó có tất cả các đối tượng giá trị dẫn xuất. Điều đó sẽ lên tới n + 1 lớp thay vì 2n lớp. Lớp ValueObject là một phần của hạt nhân được chia sẻ, vì vậy nó không liên quan trực tiếp đến mô hình. –

+1

trừ khi xử lý với 1-N (hoặc nhiều đến nhiều), sử dụng loại khung thực thể phức tạp. – Marco

4

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

  • chữ
  • Tag_Name

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.

+0

Một kỹ thuật khác mà tôi đã được thưởng thức gần đây với loại điều này là lưu trữ bộ sưu tập các đối tượng giá trị như một chuỗi Json. Đối tượng thực thể của bạn chứa bộ sưu tập có thể xử lý việc phân tích cú pháp vào và ra khỏi một chuỗi sao cho phần còn lại của mô hình của bạn vẫn làm việc với nó như một bộ sưu tập nhưng để lưu trữ nó đi vào như một chuỗi đơn giản. SQL Server cũng có thể làm việc với dữ liệu Json nếu bạn cần một truy vấn thủ công, mặc dù nó hoạt động nhiều hơn một chút. Như một phần thưởng nếu các khung nhìn của bạn đang sử dụng Ajax/Jquery, bạn chỉ có thể sử dụng thuộc tính JsonString như hiện tại. –

Các vấn đề liên quan