2011-01-21 25 views
2

我有以下兩類映射返回被引用的屬性,而不延遲加載:NHibernate的:使用SetProjection

public class Foo 
{ 
    public virtual Guid Id { get; set; } 
    public virtual Bar Bar { get; set; } 
} 
public class Bar 
{ 
    public virtual Guid Id { get; set; } 
    public virtual string Name { get; set; } 
} 

我有以下標準:

return Session.CreateCriteria<Foo>("f") 
    .CreateAlias("f.Bar", "b") 
    .SetProjection(Projections.Property("f.Bar")) 
    .List<Bar>(); 

這將生成以下SQL:

select b.Id from Foo f 
inner join Bar on f.BarId = b.Id 

請注意,只有酒吧的ID是返回,而不是整個班級。我如何獲得Bar的所有列?

+0

在您的代碼示例中,您聲明.List (); ,但是你說只有酒吧的Id被返回。這是否意味着你得到了只有Id屬性被水合的酒吧列表? – Jaguar 2011-02-22 09:11:34

回答

2

解決方案取決於您的需求。

所有首先,如果你需要返回實體吧,那麼你的初始條件的類型必須是酒吧的,所以你只是:

session.CreateCriteria<Bar>(). 
     .List<Bar(); 

如果您需要添加基於美孚則有一些限制兩種方式。

  1. 使用HQL

    session.CreateQuery(

    "select b " + 
        "from Foo f " + 
        "inner join f.Bar b " + 
        "where f.Id = 9 ") 
    .List(); 
    
  2. 使用查詢唯一的財產。通過在Bar映射文件中添加access =「noop」來完成此操作。

    <many-to-one name="foo" access="noop" class="Foo" column="FooFk"/>

請注意,您的域模型並沒有改變!您不需要在Bar類中添加該「foo」屬性/字段。 現在你可以使用這個屬性在你的查詢,如:

session.CreateCriteria<Bar>() 
    .CreateAlias("foo", "f") 
    .Add(Restrictions.Eq("f.Id", 9)) 
    .List<Bar>(); 
0

如果它不適合到一個單一的標準,使用DetachedCriteria

select Bar.* 
from Bar 
where Bar.id in (Select b.id from Foo f inner join Bar b on ...) 

var subquery = DetachedCriteria.For<Foo>("f") 
    .SetProjection(Projections.Property("f.Bar")) 
    // more filter criteria ... 

return session.CreateCriteria<Bar> 
    .SetProjection(Subqueries.PropertyIn("id", subquery)); 

其中這樣造成SQL

顯然只有在子查詢中基於Foo的過濾標準時纔有意義。

0

如果上面的分離標準查詢在這裏不起作用,那麼應該是一個簡單的HQL查詢。

var hqlQuery="select b from Foo as f inner join f.Bar as b"; 

現在如下運行此查詢:

Session.CreateQuery(hqlQuery).List<Boo>(); 

您現在可以添加where條件查詢太多,如果你想要的。

希望這可以幫助..我可以告訴你如何使用標準來做到這一點,但我認爲這對您來說更容易一點,因爲您似乎對SQL感到舒服。