Запрос на коллекцию с помощью Nhibernate Criteria Api?

У меня есть сущность "Estate", и эта сущность имеет коллекцию "EstateFeatures" (тип: EstateFeature), а EstateFeature имеет свойство "MyFeatureValue".

Примечание. Это ограниченные свойства вопроса. У всех сущностей есть идентификатор и все необходимое и т. д.

Недвижимость

IList<EstateFeature> EstateFeatures;

Недвижимость

FeatureValue MyFeatureValue;

FeatureValue

public virtual long Id;

Я пытаюсь получить недвижимость с заданным FeatureValue.Id

DetachedCriteria query = DetachedCriteria.For<Estate>();
Conjunction and = new Conjuction();
foreach (var id in idCollection)
   and.Add(Expression.Eq("MyFeatureValue.Id",id);

query
     .CreateCriteria("EstateFeatures")
     .Add(and);
IList<Estate> estates = query.GetExecutableCriteria(session).List<Estate>();

Ничего не вернулось из этого запроса, я делаю что-то не так?

Спасибо


person Barbaros Alp    schedule 10.02.2009    source источник


Ответы (7)


Вам нужно будет убедиться, что вы присоединяетесь к MyFeatureValue один раз для каждой функции, которую вы хотите иметь в своем поместье.

Один из способов - вызвать .CreateAlias ​​для каждой итерации, дать ему уникальный псевдоним, а затем добавить выражение "aliasX.Id"


foreach (var id in idCollection)
{
   query = query.CreateAlias("MyFeatureValue", "feature" + id)
                .Add(Expression.Eq("feature" + id + ".Id",id);


}

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

Тем не менее, я думаю, это поможет вам начать.

РЕДАКТИРОВАТЬ: Поскольку ошибка в Criteria API не позволяет вам многократно связывать коллекцию с помощью CreateAlias ​​или CreateCriteria, вам необходимо прибегнуть к HQL.

http://derek-says.blogspot.com/2008/06/duplicate-association-path-bug-in.html

(Hibernate страдает от той же проблемы)


select e   
FROM Estate AS e
INNER JOIN e.MyFeatureValue AS fv1
INNER JOIN e.MyFeatureValue AS fv2
WHERE fv1.Id = 3
   AND fv2.Id = 13

вам нужно будет построить HQL динамически, чтобы ваши псевдонимы стали уникальными (fv1, fv2, fvX...)

person jishi    schedule 10.02.2009
comment
Я получил сообщение об ошибке: повторяющийся путь ассоциации: MyFeatureValue - person Barbaros Alp; 11.02.2009
comment
Да, это своего рода ошибка в Criteria API. Вам придется прибегнуть к HQL, потому что я не думаю, что они это исправили. - person jishi; 11.02.2009
comment
Спасибо, Джиши, я собираюсь попробовать это знать. вернуться, когда я закончил с ним. - person Barbaros Alp; 12.02.2009

Если я правильно понимаю, думаю, что-то вроде этого может работать

CreateCriteria(typeof(Estate))
     .CreateAlias("EstateFeatures", "estatefeature")
     .Add(Restrictions.In("estatefeature.MyFeatureValue.Id", ids))
     .List<Estate>();
person Remmus    schedule 11.02.2009
comment
да, вроде... Я уже делаю это, но у меня есть коллекция id. Спасибо за ответ - person Barbaros Alp; 12.02.2009

Какой запрос сгенерировал для вас NHibernate? Вы можете проверить это, используя свойство конфигурации show_sql.

Насколько я понимаю, вы пытаетесь получить все поместья с заданным набором характеристик. Я думаю, это сгенерирует запрос, который выглядит как

SELECT ....
FROM Estates
INNER JOIN Features
WHERE Feature.Id = 1 AND Feature.Id = 2 ...

Если вы хотите получить все поместья, которые содержат все указанные функции, я думаю, вам придется использовать дизъюнкцию, чтобы NHibernate извлекал все поместья, которые имеют хотя бы одну из этих функций. Затем в вашем клиентском коде вы будете проверять каждое поместье в своем «клиентском коде», так что в конечном итоге вы просто получите поместья со всеми функциями.
Я не знаю, есть ли эффективный способ позволить NHibernate справиться с этим ...

person Frederik Gheysels    schedule 10.02.2009
comment
Разве мой запрос не возвращает поместья, которые имеют все функции (а не только одну из этих функций)? - person Barbaros Alp; 11.02.2009
comment
Не могли бы вы объяснить это более подробно? Затем в вашем клиентском коде вы должны будете проверить каждое поместье в своем «клиентском коде», так что в конечном итоге вы просто получите поместья со всеми функциями. - person Barbaros Alp; 11.02.2009

Код выглядит так, как будто вы передаете список FeaturesValueIds и хотите получить список со всеми этими функциями. Если это так, я бы взглянул на сгенерированный SQL и запустил его в базе данных, чтобы увидеть, должны ли вы что-то вернуть.

В противном случае, если вы ищете список, в котором есть какие-либо функции, которые вы передаете, вам следует использовать дизъюнкцию, а не конъюнкцию.

person RKitson    schedule 10.02.2009
comment
Когда я использую дизъюнкции, некоторые значения возвращаются из запроса, но они являются результатом, имеющим любую из этих функций. Я хочу получить результаты, которые имеют только эти функции? так мой запрос неправильный? - person Barbaros Alp; 11.02.2009
comment
{DetachableCriteria(MyFeatureValue.Id = 7 и MyFeatureValue.Id = 8 и MyFeatureValue.Id = 9 и MyFeatureValue.Id = 10 и MyFeatureValue.Id = 11 и MyFeatureValue.Id = 12 и MyFeatureValue.Id = 16)} Это запрос (отдельные критерии) - person Barbaros Alp; 11.02.2009
comment
Нет, это Detached Criteria, sql уже в пути. - person Barbaros Alp; 11.02.2009

Похоже, вы хотите or (Disjunction) вместо and (Conjunction). Прямо сейчас вы ищете объекты EstateFeatures, каждый из которых имеет несколько разных Ids, что кажется не тем, что вам нужно.

var or = new Disjunction();
foreach(var id in idCollection)
    or.Add(Expression.Eq("MyFeatureValue.Id", id);

var query = DetachedCriteria.For<Estate>();
query
    .CreateCriteria("EstateFeatures")
    .Add(and);
var estates = query.GetExecutableCriteria(session).List<Estate>();
person yfeldblum    schedule 11.02.2009
comment
Я думаю, что мне нужно сочетание, потому что мне нужны Estates, у которых есть только коллекция featureId. Он должен содержать именно их, не меньше и не больше. Разве это не союз (и)? - person Barbaros Alp; 12.02.2009
comment
Я пробовал это раньше, хорошо, я получаю Estates, но один Estate приходит более одного раза. Я использую запрос .SetResultTransformer(new NHibernate.Transform.DistinctRootEntityResultTransformer()); но это не очень хорошо работает с моим пейджингом. Сетмаксрезультат и сетфирстресулт - person Barbaros Alp; 13.02.2009
comment
Это только различает значения на каждой странице, а не во всем наборе результатов, я знаю, что это другая тема, но есть ли у вас какое-либо представление об этом? - person Barbaros Alp; 13.02.2009

Я также пробовал это, но результат тот же:

DetachedCriteria features = DetachedCriteria.For<FeatureValue>();
features.SetProjection(Projections.Property("Id"));
features.Add(Property.ForName("Id").EqProperty("value.Id"));

var and = new Conjunction();

foreach (var l in FeatureIdCollection)
    and.Add(Expression.Eq("Id", l));

features.Add(and);

query.CreateCriteria("EstateFeatures")
     .CreateCriteria("MyFeatureValue","value")
     .Add(Subqueries.Exists(features));
person Barbaros Alp    schedule 11.02.2009

person    schedule
comment
Что ж, красиво. Дай мне минуту. - person RKitson; 11.02.2009
comment
Я не вижу в критериях, где вы запрашиваете поместья, где CategoryID = 3, это может иметь какое-то отношение к этому. - person RKitson; 11.02.2009
comment
разве это не то, где CategoryID=3, ГДЕ this_.CategoryId = @p0 - person Barbaros Alp; 11.02.2009
comment
Да, но где вы просите об этом в ваших критериях? - person RKitson; 11.02.2009
comment
ооо, я вижу. Он находится в верхней части кода. Вот почему я не упомянул об этом. также я пробую без категории = 3, результат тот же. Посоветуете что-то другое или я ошибаюсь? - person Barbaros Alp; 11.02.2009