2010-03-05 36 views
3

我試圖獲得SQL像下面這樣使用NHibernate的標準API:NHibernate的:Subqueries.Exists不工作

SELECT * FROM Foo 
    WHERE EXISTS (SELECT 1 FROM Bar 
       WHERE Bar.FooId = Foo.Id 
       AND EXISTS (SELECT 1 FROM Baz 
          WHERE Baz.BarId = Bar.Id) 

所以基本上,FOOS有許多酒吧和酒吧有很多Bazes。我想要得到所有帶有Bazes酒吧的Foos。

要做到這一點,一種超然的標準似乎最好的,就像這樣:

var subquery = DetachedCriteria.For<Bar>("bar") 
    .SetProjection(Projections.Property("bar.Id")) 
    .Add(Restrictions.Eq("bar.FooId","foo.Id")) // I have also tried replacing "bar.FooId" with "bar.Foo.Id" 
    .Add(Restrictions.IsNotEmpty("bar.Bazes")); 

return Session.CreateCriteria<Foo>("foo") 
    .Add(Subqueries.Exists(subquery)) 
    .List<Foo>(); 

然而,這引發異常: System.ArgumentException:無法找到匹配的標準信息提供者:bar.FooId = foo.Id和bar.Bazes不爲空

這是NHibernate的錯誤嗎?有一個更好的方法嗎?

回答

3

嘗試在子查詢中Bar類的Foo路徑上創建條件或別名,然後應用eaual限制。

var subquery = DetachedCriteria.For<Bar>("bar") 
    .SetProjection(Projections.Property("bar.Id")) 
    .Add(Restrictions.IsNotEmpty("bar.Bazes")) 
    .CreateCriteria("Foo") 
     .Add(Restrictions.Eq("bar.FooId","Id")); 

或CreateAlias( 「富」, 「富」)

var subquery = DetachedCriteria.For<Bar>("bar") 
    .SetProjection(Projections.Property("bar.Id")) 
    .Add(Restrictions.IsNotEmpty("bar.Bazes")) 
    .CreateAlias("Foo","foo") 
    .Add(Restrictions.Eq("bar.FooId","foo.Id")); 
2

我剛剛解決了我遇到同樣的問題。

對我來說,解決方案是使用'Mapped Reference屬性'來限定'child'實體的外鍵(指向父實體)。因爲你的'childEntity.FK = parentEntity.Key'實際上等於你想使用Expression.EqProperty(..,..)而不是Expression.Eq(..,..)的屬性的屬性。 )

所以,我建議修改這一行:

Add(Restrictions.Eq("bar.FooId","foo.Id")) 

要這樣:

.Add(Restrictions.EqProperty("bar.Foo.Id","foo.Id"))