Rückgabe der Klasse aus der verschachtelten Sammlung mit NHibernate

Doman:

<code>class Action
    Products: IList of class ActionProducts: 
          Category: class Category
                Products: IList of class Product
</code>

Nun möchte ich Folgendes:

<code> 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;
</code>

Und dieser Linq funktioniert tatsächlich, aber: 1. erzeugt select für alle Tabellen anstelle von nur Products 2. erzeugt left outer joins, nicht inner 3. Distinct () in der Abfrage funktioniert nicht (obwohl ToList (). Distinct () funktioniert) .

Kann auch mit SelectMany (a => a.Products) .SelectMany (ap => ap.Category.Products) durchgeführt werden, funktioniert aber mit dem aktuellen NHibernate.Linq überhaupt nicht.

Also möchte ich ICriteria verwenden. Aber ich kann nicht sehen, wie ich das Produkt zurückschicke, nicht die Aktion?

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

Wie kann ich "SomehowReturnMeOnly" ("p")? Damit ich das machen kann

<code>return criteria.List<Product>();
</code>

Was wird scheitern, weil ICriteria Aktionen und nicht Produkte auswählt?

Ich mag HQL in Betracht ziehen, aber ich mag keine String-Abfragen ... Zum Beispiel ist hier das HQL, das genau das SQL erzeugt, das ich brauche:

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

Antworten auf die Frage(3)

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

Schauen Sie sich die nhibernate-Dokumente anHier für einige Beispiele.

 queen316. Juni 2009, 13:59
Nun, ich habe dort viele Projektionen ausprobiert, auch Projektionslisten, mit CreateCriteria anstelle von Alias ​​... alles funktioniert nicht. Hier ist die typische Ausnahme (für Ihren Code): NHibernate.QueryException: Eigenschaft konnte nicht aufgelöst werden: Category.Products von: OrderEntry3.Core.ActionProduct
Lösung für das Problem

dass CreateAlias ​​nur 1 Stufe ausführen kann)

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

Dies funktioniert und besteht den Test, erzeugt aber "SELECT FROM products WHERE id in (Unterabfrage)", was möglicherweise noch besser ist (kein DISTINCT erforderlich), aber nicht das ist, was ich erreichen wollte. Die Criteria API scheint sehr, sehr restriktiv zu sein. Also haben wir:

HQL mit Nachteilen bei String-AbfragenKriterien-API mit vielen Einschränkungen und manchmal schrecklichem Code, um einfache Ergebnisse zu erzielenNH-Linq, das sehr vielversprechend aussieht, jetzt aber unvollständig ist.

Also werde ich wohl bei HQL bleiben, bis Linq fertig ist.

Antwort nachgedacht hatte ... versuchte ich es und es schien zu funktionieren:

<code> 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")));
</code>

Es sieht so aus, als ob NHibernate keine Verschachtelung von Projektionseigenschaften zulässt, was seltsam ist. Und es funktioniert auch nicht, wenn ich mir generiertes SQL ansehe, sehe ich, dass es nur auswählt

<code>SELECT distinct c2_.Id as y0_ FROM ... Categories c2_ ...
</code>

Das heißt, es werden keine Produkte abgerufen, wodurch mein Komponententest fehlschlägt, da die zurückgegebene Liste nur Nullen anstelle von Produktinstanzen enthält.

 queen316. Juni 2009, 14:40
Hier ist die Frage mit den gleichen Ergebnissen - Nullen anstelle von Instanzen, während HQL gut funktioniert:stackoverflow.com/questions/856761/…

Ihre Antwort auf die Frage