Вопрос

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

Примечание:Это ограниченные свойства для данного вопроса.Все объекты имеют идентификатор и все необходимые параметры и т.д.

Поместье

IList<EstateFeature> EstateFeatures;

Характеристика объекта недвижимости

FeatureValue MyFeatureValue;

Отличительное значение

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>();

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

Спасибо

Это было полезно?

Решение

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

Один из способов - вызвать .Создайте ALIAS для каждой итерации, присвоите ей уникальный псевдоним, затем добавьте выражение "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

(Спящий режим также страдает от той же проблемы)

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 ...)

Другие советы

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

CreateCriteria(typeof(Estate))
     .CreateAlias("EstateFeatures", "estatefeature")
     .Add(Restrictions.In("estatefeature.MyFeatureValue.Id", ids))
     .List<Estate>();

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

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

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

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

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

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

    exec sp_executesql N'SELECT TOP 3 id11_1_, Address11_1_, Title11_1_, Descript4_11_1_, 
    Price11_1_, Discount11_1_, ForBankL7_11_1_, AddDate11_1_, LastUpdate11_1_, 
IsVisible11_1_, ViewCount11_1_, SaleOrRent11_1_, LocationId11_1_, StaffId11_1_, 
CategoryId11_1_, id27_0_, EstateId27_0_, FeatureV3_27_0_ FROM (SELECT ROW_NUMBER() 
OVER(ORDER BY __hibernate_sort_expr_0__) as row, query.id11_1_, query.Address11_1_, 
query.Title11_1_, query.Descript4_11_1_, query.Price11_1_, query.Discount11_1_, 
query.ForBankL7_11_1_, query.AddDate11_1_, query.LastUpdate11_1_, query.IsVisible11_1_, 
query.ViewCount11_1_, query.SaleOrRent11_1_, query.LocationId11_1_, query.StaffId11_1_, 
query.CategoryId11_1_, query.id27_0_, query.EstateId27_0_, query.FeatureV3_27_0_, 
query.__hibernate_sort_expr_0__ FROM (SELECT this_.id as id11_1_, this_.Address as 
Address11_1_, this_.Title as Title11_1_, this_.Description as Descript4_11_1_, this_.Price 
as Price11_1_, this_.Discount as Discount11_1_, this_.ForBankLoan as ForBankL7_11_1_, 
this_.AddDate as AddDate11_1_, this_.LastUpdate as LastUpdate11_1_, this_.IsVisible as 
IsVisible11_1_, this_.ViewCount as ViewCount11_1_, this_.SaleOrRent as SaleOrRent11_1_, 
this_.LocationId as LocationId11_1_, this_.StaffId as StaffId11_1_, this_.CategoryId as 
CategoryId11_1_, estatefeat1_.id as id27_0_, estatefeat1_.EstateId as EstateId27_0_, 
estatefeat1_.FeatureValueId as FeatureV3_27_0_, CURRENT_TIMESTAMP as 
__hibernate_sort_expr_0__ FROM Estate this_ inner join EstateFeature estatefeat1_ on 
this_.id=estatefeat1_.EstateId WHERE this_.CategoryId = @p0 and 
(estatefeat1_.FeatureValueId = @p1 and estatefeat1_.FeatureValueId = @p2 and 
estatefeat1_.FeatureValueId = @p3 and estatefeat1_.FeatureValueId = @p4 and 
estatefeat1_.FeatureValueId = @p5 and estatefeat1_.FeatureValueId = @p6 and 
estatefeat1_.FeatureValueId = @p7)) query ) page WHERE page.row > 0 ORDER BY 
__hibernate_sort_expr_0__',N'@p0 bigint,@p1 bigint,@p2 bigint,@p3 bigint,@p4 bigint,@p5 
bigint,@p6 bigint,@p7 bigint',@p0=3,@p1=7,@p2=8,@p3=9,@p4=10,@p5=11,@p6=12,@p7=16

Это выглядит так, как будто ты хочешь 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>();

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

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));
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top