NHibernate: предложение CreateCriteria и Exists

Как я могу написать следующий SQL с помощью CreateCriteria:

SELECT * FROM FooBar fb
WHERE EXISTS (SELECT FooBarId FROM Baz b WHERE b.FooBarId = fb.Id)

person cbp    schedule 18.11.2009    source источник


Ответы (3)


Вот как вы можете это сделать:

var fooBars = Session.CreateCriteria<FooBar>()
        .Add(Restrictions.IsNotEmpty("Bazs")).List<FooBar>();

... при условии, что в объекте FooBar есть свойство коллекции (один ко многим) "Bazs".

В качестве альтернативы вы можете использовать отдельные критерии, подобные этому:

DetachedCriteria dCriteria = DetachedCriteria.For<Baz>("baz")
        .SetProjection(Projections.Property("baz.FooBarId"))
        .Add(Restrictions.EqProperty("baz.FooBarId", "fooBar.Id"));

var fooBars = Session.CreateCriteria<FooBar>("fooBar")
        .Add(Subqueries.Exists(dCriteria)).List<FooBar>();
person tolism7    schedule 18.11.2009
comment
Это помогло мне устранить ОШИБКУ NHIBERNATE: не удалось найти поставщика информации о соответствующих критериях, спасибо за простой пример. - person Timbob; 04.01.2013

Только что решив связанную проблему и в конце концов придя к решению, я решил поделиться ответом здесь:

Предполагая, что вам нужен исходный запрос вопросов с дополнительным условием для подзапроса:

SELECT * FROM FooBar fb
WHERE EXISTS (SELECT FooBarId FROM Baz b WHERE b.FooBarId = fb.Id
              AND Quantity = 5)

Предполагая, что у вас есть ссылка в классе Baz на родителя, называемого, скажем, FooBarRef [в классе Fluent Map вы бы использовали метод References()], вы должны создать запрос следующим образом:

DetachedCriteria dCriteria = DetachedCriteria.For<Baz>("baz")
        .SetProjection(Projections.Property("baz.FooBarId"))
        .Add(Expression.EqProperty("this.FooBarId", "FooBarRef.Id"))
        .Add(Expression.Eq("baz.Quantity", 5));

var fooBars = Session.CreateCriteria<FooBar>("fooBar")
        .Add(Subqueries.Exists(dCriteria)).List<FooBar>();

Я не на 100% уверен в жестком кодировании псевдонима "this", который является псевдонимом, который NHibernate автоматически присваивает корневому объекту (таблице) в запросе, но это единственный найденный мной способ сослаться на ключ таблицу родительского запроса из подзапроса.

person Trevor    schedule 30.07.2010

Я придумал, как это сделать, используя выражение IsNotEmpty. Здесь используются расширения NHibernate Lambda:

Session.CreateCriteria<FooBar>()
    .Add(SqlExpression.IsNotEmpty<FooBar>(x => x.Bazes))
    .List<FooBar>();
person cbp    schedule 18.11.2009
comment
Действительно... и вы натолкнули меня на мысль, что это можно сделать проще и без расширений Nhibernate Lambda. Я отредактировал свой ответ, чтобы включить эту опцию. - person tolism7; 18.11.2009