2009-07-15 24 views
6

Tôi đang sử dụng NHibernate với truy vấn SQL để điền một số đối tượng thực thể.NHibernate - AddEntity và AddJoin

tôi có một đối tượng mục mà tham chiếu đến một đối tượng tài khoản (để chỉ chủ sở hữu của Item)

class Item 
{ 
public User User; 
} 

truy vấn SQL của tôi là (nó thực sự phức tạp hơn, đó là lý do tôi không thể sử dụng HQL, nhưng tôi bắt đầu với điều này để đảm bảo AddJoin/AddEntity đang làm việc):

SELECT {i.*}, {u.*} 
FROM Item i INNER JOIN User u ON (i.UserId = u.Id) 
WHere i.Id = 5 

đây là mã của tôi:

var x = session.CreateSQLQuery(sql) 
    .AddEntity("i", typeof(Item)) 
    .AddJoin("u", "i.User") 
    .List(); 

Khi tôi chạy điều này, tôi nhận được một mảng hai chiều. Mỗi mục trong mảng chứa một đối tượng Item (với thuộc tính User được khởi tạo) và chính đối tượng User.

Tôi đang thiếu gì? Tôi đã hy vọng sẽ nhận được một danh sách các đối tượng Item với thuộc tính User được khởi tạo (đó là cách tôi giải thích tài liệu).

Trả lời

0

Điều gì xảy ra nếu bạn bỏ qua phương thức AddJoin? Không đủ để chỉ định AddEntity?

1

Nó được một thời gian, nhưng tôi nghĩ rằng bạn đang bỏ lỡ này:

.SetResultTransformer(new DistinctEntityRootTransformer()) 
+0

Cảm ơn Ben. Tôi đã thêm điều này - .SetResultTransformer (mới DistinctRootEntityResultTransformer()) - nhưng sau đó tôi nhận được một danh sách Người dùng, thay vì danh sách các Mục mong muốn. Tôi nghĩ Root Entity sẽ là Item, nên cái gì đó khác là sai. –

+0

Điều này không hoạt động khi có một addjoin khác. Bạn cần phải cuộn DistinctRootEntityResultTransformer của riêng bạn. Xem bên dưới. – Trent

0

Nếu bản đồ của bạn là đúng, bạn chỉ có thể sử dụng lệnh JOIN lấy để có được tất cả điều này trong một hit duy nhất như vậy:

var x = session.CreateQuery("from Item i join fetch i.User").List<Item>(); 
+0

Cảm ơn bạn David, nhưng SQL thực tế phức tạp hơn nhiều so với những gì tôi đưa vào. Tôi cần phải hiểu tại sao SQL cơ bản không trả lại những gì tôi mong đợi vì tôi không thể sử dụng HQL cho giải pháp cuối cùng. –

5

Tôi chỉ lãng phí một buổi chiều để tìm hiểu điều này. SetResultTransformer (CriteriaUtil.DistinctRootEntity) hoạt động trên điều cuối cùng được thêm vào.

Đây là những gì tôi đã làm để có được thực thể đầu tiên từ truy vấn. Một trong những bắt mặc dù, tôi đã phải sửa đổi NHibernate.DistinctRootEntityResultTransformer.TransformTuple() để được ảo. Không phải là một việc lớn đối với chúng tôi, bởi vì chúng tôi đã phân nhánh NHibernate cho một số bổ sung tầm thường như thế này. Nếu bạn không muốn chi nhánh NH, nó sẽ dễ dàng để cuộn IResultTransformer của riêng bạn, đảm bảo rằng các mục là duy nhất.

thêm video này vào truy vấn của bạn:

query.SetResultTransformer(new FirstTupleDistinctResultTransformer()); 

và đây là lớp mới:

public class FirstTupleDistinctResultTransformer : DistinctRootEntityResultTransformer 
{ 
    public override object TransformTuple(object[] tuple, string[] aliases) 
    { 
     return tuple[0]; 
    } 
} 
1

thử này

using NHibernate.Transform; 
    //.. 

    var x = session.CreateSQLQuery(sql)  
    .AddEntity("i", typeof(Item))  
    .AddJoin("u", "i.User") 
    .AddEntity("i", typeof(Item)) 
    .SetResultTransformer(new DistinctRootEntityResultTransformer()) 

    .List(); 
3
var x = session.CreateSQLQuery(sql)  
    .AddEntity("i", typeof(Item))  
    .AddJoin("u", "i.User") 
    .AddEntity("i", typeof(Item)).setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY); 

nó sẽ trở lại chỉ mục