2010-01-20 47 views
7

Tôi nghĩ rằng thực thể nên thực hiện bình đẳng bằng cách so sánh khóa chính như mặc định, nhưng các tài liệu nhibernate khuyến cáo sử dụng danh tính doanh nghiệp:nhibernate: thực tiễn tốt nhất để thực hiện bình đẳng là gì?

Cách rõ ràng nhất là thực hiện Equals()/GetHashCode() bằng cách so sánh giá trị định danh của cả hai đối tượng. Nếu giá trị là như nhau, cả hai phải là cùng một hàng cơ sở dữ liệu, do đó chúng bằng nhau (nếu cả hai được thêm vào một ISet, chúng ta sẽ chỉ có một phần tử trong ISet). Thật không may, chúng tôi không thể sử dụng phương pháp đó. NHibernate sẽ chỉ gán các giá trị định danh cho các đối tượng liên tục, một cá thể mới được tạo sẽ không có bất kỳ giá trị định danh nào! Chúng tôi khuyên bạn nên triển khai Equals() và GetHashCode() bằng cách sử dụng bình đẳng khóa doanh nghiệp.

kinh doanh bình đẳng chính có nghĩa là Equals() phương pháp so sánh chỉ các thuộc tính hình thành chìa khóa kinh doanh, một chìa khóa đó sẽ xác định ví dụ của chúng ta trong thế giới thực (một phím ứng cử viên tự nhiên)

Và ví dụ (cũng từ doc):

public override bool Equals(object other) 
{ 
    if (this == other) return true; 

    Cat cat = other as Cat; 
    if (cat == null) return false; // null or not a cat 

    if (Name != cat.Name) return false; 
    if (!Birthday.Equals(cat.Birthday)) return false; 

    return true; 
} 

này khiến đầu anh quay bởi vì khái niệm về bản sắc kinh doanh (theo ví dụ) cũng giống như so sánh bằng cú pháp, mà về cơ bản là loại ngữ nghĩa tôi liên kết với ValueObjects . Lý do không sử dụng các khóa cơ sở dữ liệu chính vì giá trị so sánh sẽ thay đổi mã băm của đối tượng nếu khóa chính không được tạo ở phía máy khách (cho ex incremental) và bạn sử dụng một số loại bộ sưu tập có thể bắt đầu (chẳng hạn như ISet) để lưu trữ các thực thể của bạn.

Làm cách nào tôi có thể tạo cài đặt bình đẳng tốt mà không vi phạm các quy tắc chung về bình đẳng/mã băm (http://msdn.microsoft.com/en-us/library/bsc2ak47.aspx) và tuân thủ quy tắc nhibernate?

+0

Tại sao bạn (cụ thể) muốn/cần sử dụng Bằng? – apollodude217

Trả lời

13

Đây là vấn đề đã biết với ORM. Ở đây tôi phác thảo các giải pháp mà tôi biết và đưa ra một vài gợi ý.

1 Surrogate/khóa chính: tự động tạo ra

Như bạn mentionned, nếu đối tượng chưa được lưu, điều này không làm việc.

2 Surrogate/khóa chính: giá trị giao

Bạn có thể quyết định để gán giá trị của PK trong các mã, cách này các đối tượng luôn luôn có một ID và có thể được sử dụng để so sánh. Xem Don't let hibernate steal your identity.

3 tự nhiên quan trọng

Nếu đối tượng có một chìa khóa tự nhiên, khác với khóa chính, bạn có thể sử dụng thế này. Đây là trường hợp của một thực thể khách hàng, có một số chính là số một số khách hàng chuỗi. Số khách hàng xác định khách hàng trong thế giới thực và là một khóa tự nhiên sẽ không thay đổi.

4 đối tượng đánh giá cao

Sử dụng các giá trị đối tượng cho sự bình đẳng là có thể. Nhưng có những thiếu sót khác mà bạn đã đề cập. Điều này có thể có vấn đề nếu các giá trị thay đổi và đối tượng nằm trong bộ sưu tập .Ví dụ, nếu bạn có một Set với hai đối tượng khác nhau lúc đầu, nhưng sau đó bạn thay đổi các giá trị trong khi chúng được tham chiếu trong tập hợp sao cho chúng trở nên bằng nhau. Sau đó, bạn phá vỡ hợp đồng của Set. Xem Hibernate equals and hashcode.

5 Mixed: giá trị + AutoGenerate chính/phím thay thế

Nếu các đối tượng để so sánh có một ID đã có, sử dụng nó. Nếu không, hãy sử dụng các giá trị đối tượng để so sánh.

Tất cả đều có ưu điểm và nhược điểm. IMHO, tốt nhất là 3, nếu có thể với mô hình miền của bạn. Nếu không, tôi đã sử dụng 5 và nó đã hoạt động, mặc dù vẫn còn một số bẫy khi sử dụng các bộ sưu tập. Tôi không bao giờ sử dụng 2 nhưng đó cũng là một giải pháp hợp lý, nếu bạn tìm cách tạo PK trong mã. Có lẽ người khác có con trỏ cho cái này.

+0

Tôi không thấy lựa chọn 1 là một vấn đề nếu bạn không băm các thực thể của bạn trước khi kiên trì chúng (ví dụ, không sử dụng các bộ sưu tập ISet). – Marius

+0

Đẹp nhất (+1) Xin chúc mừng –

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