2010-11-30 6 views
3

Ich benutze Nhibernate v2.1.2.4000. Mit many-to-many-Beziehung zwischen Beiträge ein Schlagwörter Ich habe die Abfrage:Linq zu NHibernate - Bestellung anonymer Typ

tags 
.Select(t => new { Name = t.Name, Count = t.Posts.Count }) 
.OrderBy(x => x.Count); 

anonymen Typ Bestellung fehlschlägt (Verweis nicht auf eine Instanz eines Objekts festgelegt). Hat dieses Problem etwas mit LinqToNH zu tun? Was kann die Ursache für diesen Fehler sein? Was ist die Lösung? Wenn es etwas mit LinqToNH verbunden ist, dann wie kann es mit einer anderen Option (dh Kriterien-API) gelöst werden?

EDIT: Wenn ich Adams ICriteria Option versuchen, sagt SQLProfiler ausgeführt Skript ist:

SELECT this_.Name as y0_, count(this_.Id) as y1_ FROM Tag this_ GROUP BY this_.Name ORDER BY count(this_.Id) asc 

Mapping für Tag:

public class TagMap : ClassMap<Tag> 
{ 
    public TagMap() 
    { 
     Table("Tag"); 
     Id(x => x.Id).GeneratedBy.GuidComb(); 
     Map(x => x.Name); 
     HasManyToMany(x => x.Posts) 
      .Table("PostTags") 
      .ChildKeyColumn("Post") 
      .ParentKeyColumn("Tag") 
      .Cascade.None().Inverse(); 
    } 
} 

Antwort

2

Es gibt viele Dinge in NHibernate.Linq für NHibernate 2.1.2.4000 das wird einfach nicht funktionieren. Sie können stattdessen HQL oder ICriteria verwenden oder auf NHibernate 3.0 aktualisieren. Wenn Sie alle Daten verwenden möchten, erzwingen Sie, dass Ihre Linq-Abfrage nach Select ausgeführt wird, indem Sie eine ToList hinzufügen.

tags 
    .Select(t = new { t.Name, t.Posts.Count }) 
    .ToList() 
    .OrderBy(x => x.Count); 

Das anonyme Objekt an sich ist etwas, das NHibernate.Linq definitiv behandeln kann.

Übrigens müssen Sie den Feldnamen in einem anonymen Objekt nicht angeben, wenn es mit dem Feld/der Eigenschaft identisch ist, von dem Sie es ziehen.

EDIT: Eine ICriteria Version dieser Abfrage würde wie folgt aussehen ...

var tags = session.CreateCriteria(typeof(Tag), "tag") 
    .SetProjection(
     Projections.GroupProperty("tag.Name"), 
     Projections.Count("tag.Posts")) 
    .AddOrder(Order.Asc(Projections.Count("tag.Posts"))) 
    .List(); 

EDIT: Mit einer richtigen Zuordnung ich die gleiche SQL bekommen, Arch. Meine frühere Zuordnung war falsch. Dieser scheint jedoch zu funktionieren.

var tags = session.CreateCriteria(typeof(Tag), "tag") 
    .CreateCriteria("tag.Posts", "post") 
    .SetProjection(
     Projections.GroupProperty("tag.Name"), 
     Projections.Count("post.Id")) 
    .AddOrder(Order.Asc(Projections.Count("post.Id"))) 
    .List(); 

Die SQL ich das bekommen, ist ...

SELECT this_.Name as y0_, count(post1_.Id) as y1_ FROM Tag this_ inner join Post_Tags posts3_ on this_.Id=posts3_.Tag inner join Post post1_ on posts3_.Post=post1_.Id GROUP BY this_.Name ORDER BY count(post1_.Id) asc 
+0

danke für die Antwort wechseln. Ein Upgrade auf 3.0 ist zur Zeit leider nicht möglich. Wie kann es mit der Kriterien-API geschrieben werden? Außerdem habe ich die Frage für die Kriterien-API-Option bearbeitet. – rovsen

+0

Adam, wenn ich versuche, diese ICriteria-Version in der Ergebnismenge ist immer 1, obwohl nicht alle sie sind 1. Haben Sie eine Idee, warum das passiert? – rovsen

+0

Können Sie eine Eins-zu-viele-Beziehung anstelle einer Viele-zu-Viele-Beziehung definieren? Haben Sie Zugriff auf SQL Server Profiler? Versuchen Sie, das auszuführen und zu sehen, welche SQL Sie aus dem Anruf erhalten. Ich habe eine Demo-App gebaut, um meine ICriteria zu testen, aber ich habe hier keinen Zugriff darauf. –

1

Versuchen erste Bestellung und dann auswählen. Ich habe sehr ähnliche Fragen zu 2.1.2.4, die perfekt funktionieren.

Edit: Versuchen Sie auch zwischen Count und Count()

+0

danke für die Antwort. Es hat nicht für mich funktioniert. – rovsen