2009-06-16 8 views
3

Doman:classe de retour de la collection nichée en utilisant NHibernate

class Action 
    Products: IList of class ActionProducts: 
      Category: class Category 
       Products: IList of class Product 

Maintenant, je veux ceci:

var products = from a in Session.Linq<Action>() 
       from ap in a.Products 
       from p in ap.Category.Products 
       where a.Name == name 
       select p; 

Et ce Linq fonctionne réellement, mais: 1. produit de sélection pour toutes les tables au lieu de seulement les produits 2. produit des jointures externes gauche, pas interne 3. Distinct() sur la requête ne fonctionne pas (bien que ToList() .Distinct() fonctionne).

Peut également être fait avec SelectMany (a => a.Products) .SelectMany (ap => ap.Category.Products) mais il ne fonctionne pas du tout avec NHibernate.Linq actuel. Donc je veux utiliser ICriteria. Mais je ne peux pas voir comment je retourne le produit, pas l'action?

ICriteria criteria = Session.CreateCriteria(typeof(Action)) 
    .Add(Expression.Eq("Name", name)) 
    .CreateAlias("Products", "ap") 
    .CreateAlias("ap.Category.Products", "p") 
    .SomehowReturnMeOnly("p"); 

Alors, comment puis-je effectuer une opération SomeReturnMeOnly ("p")? Alors que je peux faire

return criteria.List<Product>(); 

qui échouera parce que ICriteria sélectionne des actions, pas des produits?

je considérer HQL mais je ne fait pas comme les requêtes de chaîne ... Juste par exemple, voici la HQL qui fonctionne et produit exactement le SQL que j'ai besoin:

IQuery query = Session.CreateQuery("select distinct p from Action a inner join a.Products as ap inner join ap.Category.Products as p"); 
return query.List<Product>(); 

Répondre

2

Maintenant, quelque chose de semblable peut être fait (en gardant à l'esprit que createAlias ​​ne peuvent faire 1 niveau) en utilisant

DetachedCriteria dq = DetachedCriteria.For<Action>() 
    .Add(Expression.Eq("Name", name)) 
    .CreateAlias("Products", "ap") 
    .CreateAlias("ap.Category", "c") 
    .CreateAlias("c.Products", "p") 
    .SetProjection(Projections.Property("p.Id")); 
    ICriteria criteria = Session.CreateCriteria(typeof(Product)) 
    .Add(Subqueries.PropertyIn("Id", dq)); 
    return criteria.List<Product>(); 

Cela fonctionne et passe test, mais produit « SELECT FROM produits WHERE id dans (sous-requête) » ce qui peut être encore mieux (pas DISTINCT requis) mais ce n'est pas ce que je voulais atteindre. On dirait que l'API Criteria est très, très restrictive. Nous avons donc:

  1. HQL avec des inconvénients chaîne de requête
  2. API Critères avec beaucoup de restrictions et parfois du code terrible pour obtenir des résultats simples
  3. NH-Linq qui semble très prometteur, mais est incomplète maintenant.

Donc je pense que je vais rester avec HQL jusqu'à ce que Linq soit prêt.

1

Vous devez utiliser des projections , quelque chose comme ceci:

ICriteria criteria = Session.CreateCriteria(typeof(Action)) 
    .Add(Expression.Eq("Name", name)) 
    .CreateAlias("Products", "ap") 
    .CreateAlias("ap.Category.Products", "p") 
    .SetProjection(Projections.Property("ap.Category.Products")) 
    .List<Product>(); 

Jetez un oeil à la NHibernate docs here pour quelques exemples.

+0

Eh bien j'ai essayé beaucoup de projections là-bas, aussi des listes de projections, avec CreateCriteria au lieu de Alias, aussi ... tout ne fonctionne pas. Voici l'exception typique (pour votre code): NHibernate.QueryException: n'a pas pu résoudre la propriété: Category.Products de: OrderEntry3.Core.ActionProduct – queen3

0

Eh bien, après avoir réfléchi à la réponse de Chris ... J'ai essayé et il a semblé fonctionner:

ICriteria criteria = Session.CreateCriteria(typeof(Action)) 
    .Add(Expression.Eq("Name", name)) 
    .CreateAlias("Products", "ap") 
    .CreateAlias("ap.Category", "c") 
    .SetProjection(Projections.Distinct(Projections.Property("c.Products"))); 

On dirait NHibernate ne permet pas l'imbrication profonde des propriétés de projection qui est étrange. Et cela ne fonctionne pas non plus, regardant SQL généré je vois qu'il ne sélectionne que

SELECT distinct c2_.Id as y0_ FROM ... Categories c2_ ... 

-à-dire qu'il ne va pas chercher vraiment des produits, ce qui rend mon test unitaire à l'échec parce que la liste ne contient que de retour de produit au lieu nulls instances.

+0

Voici la question avec les mêmes résultats - les nulls au lieu des instances, alors que HQL fonctionne bien: http://stackoverflow.com/questions/856761/does-nhibernate-criteria-api-support-projections-on-collection-properties – queen3

Questions connexes