Frage

Ich habe eine „Estate“-Entität und diese Entität hat eine Sammlung „EstateFeatures“ (Typ:EstateFeature) und EstateFeature hat eine Eigenschaft „MyFeatureValue“.

Notiz:Dies sind die eingeschränkten Eigenschaften für die Frage.Alle Entitäten haben eine ID und alles Notwendige usw

Anwesen

IList<EstateFeature> EstateFeatures;

EstateFeature

FeatureValue MyFeatureValue;

FeatureValue

public virtual long Id;

Ich versuche, Immobilien zu erhalten, die die angegebene FeatureValue.Id haben

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

Von dieser Abfrage wurde nichts zurückgegeben. Mache ich etwas falsch?

Danke

War es hilfreich?

Lösung

Sie müssen sicherstellen, dass Sie MyFeatureValue für jede Funktion, die Ihr Anwesen haben soll, einmal beitreten.

Eine Möglichkeit besteht darin, .CreateAlias ​​für jede Iteration aufzurufen, ihr einen eindeutigen Alias ​​zu geben und dann den Ausdruck „aliasX.Id“ hinzuzufügen.

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


}

Ich kann mich nicht wirklich erinnern, wie die Syntax funktioniert, ich habe das aus meinem Kopf heraus geschrieben, bin mir auch nicht sicher, ob Sie die Abfrage neu deklarieren müssen :)

Ich denke jedoch, dass dies Ihnen den Einstieg erleichtern wird.

BEARBEITEN:Da ein Fehler in der Criteria-API Sie daran hindert, eine Sammlung mehrmals mit CreateAlias ​​oder CreateCriteria zu verknüpfen, müssen Sie auf HQL zurückgreifen.

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

(Hibernate leidet ebenfalls unter dem gleichen Problem)

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

Sie müssen die HQL dynamisch erstellen, damit Ihre Aliase eindeutig werden (fv1, fv2, fvX ...)

Andere Tipps

Wenn ich das richtig verstanden, ich glaube, so etwas wie dies funktionieren könnte

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

Welche Abfrage hat NHibernate für Sie generieren? Sie können dies überprüfen, indem Sie die show_sql Config Eigenschaft.

Wie ich Ihre Frage zu sehen, Sie versuchen, alle Stände zu erhalten, die einen bestimmten Satz von Funktionen hat. Ich denke, wird dies eine Abfrage erzeugen, die wie

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

Wenn Sie alle Stände abrufen möchten, die alle angegebenen Merkmale enthalten, ich glaube, Sie werden eine Disjunktion verwenden müssen, so dass NHibernate alle Estates abruft, die mindestens eines dieser Merkmale aufweisen. Dann in Ihrem Client-Code, haben Sie jedes Estate in Ihrem Client-Code 'überprüfen, so dass Sie schließlich nur mit Estates am Ende, die alle Funktionen.
Ich weiß nicht, ob es eine effiziente Möglichkeit der Vermietung NHibernate damit umgehen ist ...

Der Code sieht aus wie Sie in einer Liste von FeaturesValueIds und wollen eine Liste unterwegs sind, die alle diese Eigenschaften hat. Wenn das der Fall ist, habe ich einen Blick auf die SQL nehmen würde, die erzeugt wird, und es in der Datenbank ausführen, um zu sehen, wenn Sie etwas immer wieder werden sollte.

Andernfalls, wenn Sie für eine Liste suchen, der Sie in sind vorbei eine der Eigenschaften hat, sollten Sie eine Disjunktion verwenden, anstatt eine Konjunktion.

    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

Es sieht aus wie Sie or (Disjunction) statt and (Conjunction) wollen. Gerade jetzt, Sie suchen nach EstateFeatures Objekten, so dass jedes Objekt mehr verschiedenen Ids hat, was nicht zu sein, was scheint, Sie wollen.

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

Ich habe auch versucht dies, aber das Ergebnis ist das gleiche:

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));
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top