Domanda

Ho un'entità "Estate" e questa entità ha una raccolta "EstateFeatures" (tipo: EstateFeature) e EstateFeature ha una proprietà "MyFeatureValue".

Nota:Queste sono le proprietà limitate per la domanda.Tutte le entità hanno un ID e tutto ciò che è necessario, ecc

Proprietà

IList<EstateFeature> EstateFeatures;

Funzionalità immobiliare

FeatureValue MyFeatureValue;

ValoreCaratteristica

public virtual long Id;

Sto cercando di ottenere immobili con il FeatureValue.Id specificato

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

Non è stato restituito nulla da questa query, sto facendo qualcosa di sbagliato?

Grazie

È stato utile?

Soluzione

Dovrai assicurarti di iscriverti a MyFeatureValue una volta per ogni funzionalità che desideri che la tua proprietà abbia.

Un modo è chiamare .CreateAlias ​​per ogni iterazione, assegnargli un alias univoco quindi aggiungere l'espressione "aliasX.Id"

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


}

Non ricordo davvero come va la sintassi, l'ho scritto fuori dalla mia testa, non sono sicuro se sia necessario dichiarare nuovamente la query :)

Tuttavia, penso che questo ti aiuterà a iniziare.

MODIFICARE:Poiché un bug nell'API Criteria ti impedisce di associare una raccolta più volte utilizzando CreateAlias ​​o CreateCriteria, devi ricorrere a HQL.

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

(Anche l'ibernazione soffre dello stesso problema)

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

dovrai costruire l'HQL dinamicamente in modo che i tuoi alias diventino unici (fv1, fv2, fvX ...)

Altri suggerimenti

Se ho capito bene penso che qualcosa di simile potrebbe funzionare

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

Che domanda NHibernate ha generato per te? È possibile controllare questo utilizzando la proprietà di configurazione show_sql.

Per come la vedo la tua ricerca, si sta cercando di ottenere tutti Estates che hanno un dato insieme di caratteristiche. Penso, questo genererà una domanda che si presenta come

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

Se si desidera recuperare tutti i beni che contengono tutte le caratteristiche specificate, penso che dovrete usare una disgiunzione, in modo che NHibernate recupera tutti immobili che hanno almeno una di quelle caratteristiche. Poi, nel tuo client-codice, dovrete ispezionare ogni immobiliare nel 'codice client', in modo che alla fine solo finisce con immobili che hanno tutte le caratteristiche.
Non so se c'è un modo efficiente di lasciare NHibernate gestire questo ...

Il codice sembra si passa in un elenco di FeaturesValueIds e si desidera una lista che ha tutte quelle caratteristiche. Se questo è il caso, mi piacerebbe prendere uno sguardo al SQL che viene generato ed eseguirlo sul database per vedere se si dovrebbe essere sempre di nuovo nulla.

In caso contrario, se siete alla ricerca di una lista che ha nessuna delle caratteristiche che si sta passando, è necessario utilizzare una disgiunzione, piuttosto che una congiunzione.

    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

Sembra che si desidera or (Disjunction) al posto di and (Conjunction). In questo momento, si sta cercando EstateFeatures oggetti tale che ogni oggetto ha più Ids diverse, che sembra non essere ciò che si desidera.

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

Ho provato anche questo, ma il risultato è lo stesso:

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));
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top