NHibernate QueryOver Unterabfrage
Habe ich mir angeschaut, die ähnliche Fragen, aber nicht finden können, eine einfache Erklärung. Hätte ich es verpasst, aber ich verspreche, dass ich sah. Eigentlich kann ich nicht einmal finden Sie in der Dokumentation andere als einen einzelnen blog-post, die Glossen über alles, was schnell und davon ausgegangen, dass Sie vertraut sind mit anderen Formen von NH.
Gegeben, eine viele-zu-viele-zwischen Program
und Topic
, wo die letztere ist in eine Hierarchie von Topics
möchte ich abrufen alle Programs
für einen bestimmten Topic
, möglicherweise einschließlich seiner Unterthemen. Da kann ein Programm aufgeführt werden, unter mehreren sub-Themen von einem bestimmten übergeordneten Thema, ich brauche eine Unterabfrage verwenden, oder deal mit, dass Sie eindeutige (und der einfache Ansatz von TransformUsing(Transformers.DistinctRootEntity)
hat nicht funktioniert).
Raw-SQL sollte so etwas wie
SELECT ProgramId, Title, bar, baz, foo FROM Programs
WHERE ProgramId IN
(SELECT ProgramId from Program_Topics WHERE TopicId IN (1, 2, ...))
Die Ergebnisse geworfen werden, in eine Modell-Typ für die übertragung an den view. Mein Erster Versuch war dieser:
ProgramDTO pDTO = null;
/* topicIds is List<int> passed into function */
var query = Session.QueryOver<Program>()
.JoinQueryOver<Topic>(p => p.Topics)
.WhereRestrictionOn(pt => pt.Id).IsInG<int>(topicIds)
.TransformUsing(Transformers.DistinctRootEntity)
.SelectList(list => list
.Select(program => program.Id).WithAlias(() => pDTO.Id)
.Select(program => program.Title).WithAlias(() => pDTO.Title)
.Select(program => program.Location).WithAlias(() => pDTO.Location)
.Select(program => program.Description).WithAlias(() => pDTO.Description)
)
.TransformUsing(Transformers.AliasToBean(typeof(ProgramDTO)));
return query.List<ProgramDTO>();
Offensichtlich läuft ein join statt Unterabfrage, aber ich kann nicht finden, ein Beispiel für eine Unterabfrage mit einer viele-zu-viele-wie diese.
public class Program : Entity {
public virtual ISet<Topic> Topics { get; protected internal set; }
...
}
public class Topic : Entity {
public virtual ISet<Program> Programs { get; protected internal set; }
public virtual Topic ParentTopic { get; protected internal set; }
...
}
Du musst angemeldet sein, um einen Kommentar abzugeben.
Müssen Sie erstellen eine dettached-Abfrage mit der Id und verwenden Sie dann diese sub-query mit der Haupt-Abfrage.
Habe ich eingefügt, ein Beispiel hier, also müssen Sie ersetzen die entsprechenden bits mit Ihrem Klassennamen etc.
Zuerst die set-up (Sie können dies ignorieren bit):-
Nun die dettached Abfrage:-
Und das Letzte bit ist, um es alle zusammen:-
Dadurch wird der folgende SQL -: -
Hoffentlich werden Sie in der Lage, befolgen Sie diese mit Ihrer Klasse/property-Namen.
SELECT * FROM cmspage WHERE id IN (SELECT ... cmsPageId FROM cmsregioncontent WHERE regionid IN ( ... ))
zu dem, was Sie dort haben. Die version, die hier gegeben werden ist wirklich nicht viel anders als das, nur tun, eine Innere Verknüpfung.var topicSubQuery = QueryOver.Of<Topic>().WhereRestrictionOn(pt => pt.Id).IsIn(topicIds).Select(Projections.Distinct(Projections.Property<Program>(p => p.Id)));
var progQuery = Session.QueryOver<Program>().Where(p => p.Status != ProgramStatus.Archived).JoinQueryOver<Topic>(p => p.Topics).WithSubquery.WhereProperty(pt => pt.Id).In(topicSubQuery).SelectList(list => list /* ...snip... */) .TransformUsing(Transformers.AliasToBean(typeof(ProgramDTO)));
Gut, Hash an, und einige mehr, und während ich nicht wie ein Teil der Ergebnisse, es funktioniert:
Diese produziert
Dies kann eine Einschränkung der NH, aber es gibt keine müssen beitreten Programme Tabelle in der Unterabfrage. Ich habe versucht, dies zu schreiben, aus der anderen Richtung-das heißt, zum erstellen eines
QueryOver.Of<Topic>()
, aber ich konnte nicht herausfinden, wie Sie die Programm-IDs am Ende -- wählen war nur, dass Sie mir die TopicIds, und selbst dann die Abfrage war noch Eintritt in alle drei Tabellen.Ich bin mir nicht sicher, ob MS-SQL-Abfrage-Optimierer zu vermeiden, die nutzlos beitreten oder nicht, aber es wäre schön, wenn wir nicht auf Sie verlassen.
Für jetzt aber, das funktioniert, und ich hoffe, jemand anderes hat weniger Kopfschmerzen, als ich es Tat versuchen, um dies herauszufinden.