Pergunta

Eu tenho uma entidade "Estate", e esta entidade tem uma coleção "EstateFeatures" (tipo: EstateFeature). E EstateFeature tem uma propriedade "MyFeatureValue"

Nota: Estas são as propriedades limitadas para a questão. Todas as entidades tem um ID e todos necesarry etc

Estate

IList<EstateFeature> EstateFeatures;

EstateFeature

FeatureValue MyFeatureValue;

FeatureValue

public virtual long Id;

Eu estou tentando obter imóveis que o dado 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>();

Nada retornado desta consulta, estou fazendo algo errado?

Graças

Foi útil?

Solução

Você vai precisar para se certificar de que você se juntar MyFeatureValue uma vez para cada recurso que você quer que seu Estate ter.

Uma maneira é chamar .CreateAlias ??para cada iteração, dar-lhe um alias únicas em seguida, adicione a expressão "aliasX.Id"

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


}

Doesnt realmente lembrar como a sintaxe vai, escreveu esta fora da minha cabeça, não tenho certeza se você precisa redeclare consulta ou:)

No entanto, eu acho que isso irá ajudar a começar.

EDIT: Uma vez que um bug na API Critérios conter-lo de associar uma coleção várias vezes usando CreateAlias ??ou CreateCriteria, você precisa de recorrer a HQL

.

http: // Derek-diz .blogspot.com / 2008/06 / duplicado-association-path-bug-in.html

(sofre Hibernate na mesma edição aswell)

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

Você vai precisar para construir o HQL dinamicamente para que seus aliases torna único (FV1, fv2, FVX ...)

Outras dicas

Se bem entendi Eu acho que algo como este trabalho poder

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

O que consulta que NHibernate gerar para você? Você pode verificar isso usando a propriedade de configuração show_sql.

Como eu vejo a sua consulta, você está tentando fazer com que todos os Estates que têm um determinado conjunto de características. Eu acho que, isso vai gerar uma consulta que se parece com

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

Se você deseja recuperar todas as propriedades que contêm todas as características especificadas, eu acho que você terá que usar uma disjunção, para que NHibernate recupera todos os Estates que têm pelo menos uma dessas características. Então, em seu cliente-code, você terá que inspecionar cada Estate no seu 'código de cliente', de modo que você, eventualmente, acabar com Estates que têm todos os recursos.
Eu não sei se existe uma maneira eficiente de deixar NHibernate lidar com isso ...

Os olhares de código, como você está passando em uma lista de FeaturesValueIds e quer uma lista que tem todas essas características. Se for esse o caso, eu tomaria um olhar para o SQL que está sendo gerada, e executá-lo no banco de dados para ver se você deve estar recebendo nada de volta.

Caso contrário, se você estiver procurando por uma lista que tem qualquer um dos recursos que você está passando, você deve usar uma disjunção em vez de uma conjunção.

    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

Parece que você quer or (Disjunction) em vez de and (Conjunction). Agora, você está procurando EstateFeatures objetos de tal forma que cada objeto tem vários Ids diferentes, o que parece não ser o que quiser.

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

Eu também tentei isso, mas o resultado é o mesmo:

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));
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top