Question

J'ai une entité « Estate », et cette entité a une collection « EstateFeatures » (type : EstateFeature) et EstateFeature a une propriété « MyFeatureValue ».

Note:Ce sont les propriétés limitées de la question.Toutes les entités ont un identifiant et tout ce qui est nécessaire, etc.

Domaine

IList<EstateFeature> EstateFeatures;

Caractéristique du domaine

FeatureValue MyFeatureValue;

Valeur de la fonctionnalité

public virtual long Id;

J'essaie d'obtenir des biens immobiliers qui ont le FeatureValue.Id donné.

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

Cette requête n'a rien renvoyé, est-ce que je fais quelque chose de mal ?

Merci

Était-ce utile?

La solution

Vous devrez vous assurer de rejoindre MyFeatureValue une fois pour chaque fonctionnalité que vous souhaitez doter de votre domaine.

Une solution consiste à appeler .CreateAlias ​​pour chaque itération, à lui donner un alias unique puis à ajouter l'expression "aliasX.Id".

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


}

Je ne me souviens pas vraiment de la syntaxe, j'ai écrit ceci de ma tête, je ne sais pas non plus si vous devez redéclarer la requête :)

Cependant, je pense que cela vous aidera à démarrer.

MODIFIER:Puisqu'un bug dans l'API Criteria vous empêche d'associer une collection plusieurs fois à l'aide de CreateAlias ​​ou CreateCriteria, vous devez recourir à HQL.

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

(Hibernate souffre également du même problème)

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

vous devrez construire le HQL dynamiquement pour que vos alias deviennent uniques (fv1, fv2, fvX...)

Autres conseils

Si je comprends bien je pense que quelque chose comme cela pourrait fonctionner

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

Quelle requête ne NHibernate générer pour vous? Vous pouvez le vérifier en utilisant la propriété config show_sql.

Comme je vois votre requête, vous essayez d'obtenir tous les états qui ont un ensemble de caractéristiques données. Je pense, cela va générer une requête qui ressemble à

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

Si vous voulez récupérer tous les domaines qui contiennent toutes les caractéristiques spécifiées, je pense que vous devrez utiliser un Disjunction, de sorte que NHibernate récupère tous les états qui ont au moins une de ces caractéristiques. Ensuite, dans votre client-code, vous aurez tous les inspecter dans votre domaine « code client », de sorte que vous venez de finir finalement avec Estates qui ont toutes les caractéristiques.
Je ne sais pas s'il y a un moyen efficace de laisser gérer cette NHibernate ...

Le code semble que vous passez dans une liste de FeaturesValueIds et que vous voulez une liste qui a toutes ces caractéristiques. Si tel est le cas, je prendrais un coup d'oeil au SQL qui est généré, et l'exécuter contre la base de données pour voir si vous devriez obtenir quelque chose de nouveau.

Dans le cas contraire, si vous êtes à la recherche d'une liste qui a une des fonctionnalités que vous croiserez, vous devez utiliser un Disjunction plutôt que Conjonction.

    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

On dirait que vous voulez or (Disjunction) au lieu de and (Conjunction). En ce moment, vous êtes à la recherche d'objets EstateFeatures de sorte que chaque objet a plusieurs différents Ids, ce qui ne semble pas être ce que vous voulez.

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

J'ai aussi essayé, mais le résultat est le même:

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));
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top