2009-05-08 5 views
0

Ich bin auf der Suche nach einer Möglichkeit zum Abrufen der "umgebenden" Zeilen in einer NHibernate-Abfrage mit einem Primärschlüssel und einer Sortierreihenfolge?Holen Sie "umgebende" Zeilen in NHibernate Abfrage

z. Ich habe eine Tabelle mit Protokolleinträgen und möchte den Eintrag mit Primärschlüssel 4242 und den vorherigen 5 Einträgen sowie die folgenden 5 Einträge nach Datum geordnet anzeigen (es besteht keine direkte Beziehung zwischen Datum und Primärschlüssel). Solch eine Abfrage sollte insgesamt 11 Zeilen zurückgeben (solange wir nicht nahe an einem der beiden Enden sind).

Die Log-Entry-Tabelle kann riesig sein und alle abrufen, um herauszufinden, ist nicht möglich.

Gibt es ein Konzept wie die Zeilennummer, das innerhalb von NHibernate verwendet werden kann? Die zugrunde liegende Datenbank wird entweder SQlite oder Microsoft SQL Server sein.

Edited Added Probe

Daten Stellen Sie sich vor, wie die folgenden:

Id Time 
4237 10:00 
4238 10:00 
1236 10:01 
1237 10:01 
1238 10:02 
4239 10:03 
4240 10:04 
4241 10:04 
4242 10:04 <-- requested "center" row 
4243 10:04 
4244 10:05 
4245 10:06 
4246 10:07 
4247 10:08 

Wenn Sie die Eingabe mit Primärschlüssel 4242 anfordernden wir sollten die Zeilen 1237, 1238 und 4239 bis 4247 Die Bestellung erhalten ist nach Zeit, Id.

Ist es möglich, die Einträge in einer einzigen Abfrage (die natürlich Unterabfragen enthalten kann) abrufen? Die Zeit ist eine nicht eindeutige Spalte, daher haben mehrere Einträge den gleichen Wert und in diesem Beispiel ist es nicht möglich, die Auflösung so zu ändern, dass sie einzigartig ist!

Antwort

1

"Es gibt keine direkte Beziehung zwischen Datum und Primärschlüssel" bedeutet, dass die Primärschlüssel nicht in einer sequenziellen Reihenfolge sind?

Dann würde ich es tun, wie folgt:

Item middleItem = Session.Get(id); 

IList<Item> previousFiveItems = Session.CreateCriteria((typeof(Item)) 
    .Add(Expression.Le("Time", middleItem.Time)) 
    .AddOrder(Order.Desc("Time")) 
    .SetMaxResults(5); 

IList<Item> nextFiveItems = Session.CreateCriteria((typeof(Item)) 
    .Add(Expression.Gt("Time", middleItem.Time)) 
    .AddOrder(Order.Asc("Time")) 
    .SetMaxResults(5); 

Es besteht das Risiko mehrere Elemente mit der gleichen Zeit zu haben.


bearbeiten

Dies sollte jetzt funktionieren.

Item middleItem = Session.Get(id); 

IList<Item> previousFiveItems = Session.CreateCriteria((typeof(Item)) 
    .Add(Expression.Le("Time", middleItem.Time)) // less or equal 
    .Add(Expression.Not(Expression.IdEq(middleItem.id))) // but not the middle 
    .AddOrder(Order.Desc("Time")) 
    .SetMaxResults(5); 

IList<Item> nextFiveItems = Session.CreateCriteria((typeof(Item)) 
    .Add(Expression.Gt("Time", middleItem.Time)) // greater 
    .AddOrder(Order.Asc("Time")) 
    .SetMaxResults(5); 
+0

Ich denke, dass dies so lange arbeiten wie die Reihenfolge auf einer Säule, die eindeutigen Werte enthält. Es könnte sein, dass ich nach verschiedenen Spalten sortieren muss, damit eine Sequenzspalte nicht funktioniert. Ich war auf der Suche nach einer Lösung für rownum für Situationen, in denen ich auf nicht eindeutige Spalten sortieren musste, so dass mehr Ideen mehr als willkommen sind :-) – HakonB

+0

Ok, verfeinert es. Siehe den neuen Abschnitt. –

0

Diese mit NHibernate Criteria API relativ einfach sein sollte:

List<LogEntry> logEntries = session.CreateCriteria(typeof(LogEntry)) 
.Add(Expression.InG<int>(Projections.Property("Id"), listOfIds)) 
.AddOrder(Order.Desc("EntryDate")) 
.List<LogEntry>(); 

Hier Ihre listOfIds ist nur eine stark typisierte Liste von ganzen Zahlen, die IDs der Einträge repräsentieren Sie (Integer abrufen möchten 4242-5 durch 4242 + 5).

Natürlich können Sie auch Expressions hinzufügen, mit denen Sie Ids größer als 4242-5 und kleiner als 4242 + 5 abrufen können.

+1

Wie werde ich jemals Ansehen bekommen? :) Als ich innerhalb von 5 Minuten eine Antwort gepostet habe, hat jemand anderes auch eine gepostet. –

+0

Es ist wie mit Geld. Wenn du es hast, bekommst du es. Die Leute wählen häufiger für Antworten von Mitgliedern mit hohem Ansehen. Das Leben ist nicht fair. Aber egal, gute Antworten werden immer geschätzt und sollten die Hauptabsicht sein. –

+0

Wie Stefan oben bemerkt, gibt es keine direkte Beziehung zwischen Datum und Primärschlüssel, so dass nur die Auswahl per Primärschlüssel nicht funktioniert. Ich habe vielleicht eine Lösung, bei der ich auch nach Kategorie filtern muss, die die Primärschlüssellösung ungültig macht. – HakonB

0

Stefans Lösung funktioniert auf jeden Fall aber bessere Weise eine einzelne auswählen und verschachtelte Unterabfragen existiert mit:

ICriteria crit = NHibernateSession.CreateCriteria(typeof(Item)); 

     DetachedCriteria dcMiddleTime = 
      DetachedCriteria.For(typeof(Item)).SetProjection(Property.ForName("Time")) 
      .Add(Restrictions.Eq("Id", id)); 

     DetachedCriteria dcAfterTime = 
      DetachedCriteria.For(typeof(Item)).SetMaxResults(5).SetProjection(Property.ForName("Id")) 
      .Add(Subqueries.PropertyGt("Time", dcMiddleTime)); 
     DetachedCriteria dcBeforeTime = 
      DetachedCriteria.For(typeof(Item)).SetMaxResults(5).SetProjection(Property.ForName("Id")) 
       .Add(Subqueries.PropertyLt("Time", dcMiddleTime)); 

     crit.AddOrder(Order.Asc("Time")); 
     crit.Add(Restrictions.Eq("Id", id) || Subqueries.PropertyIn("Id", dcAfterTime) || 
       Subqueries.PropertyIn("Id", dcBeforeTime)); 

     return crit.List<Item>(); 

Dies ist NHibernate 2.0 Syntax, aber das gleiche gilt für frühere Versionen gilt, wenn anstelle von Einschränkungen Sie Expression verwenden.

Ich habe diese Anwendung auf einem Test getestet und es funktioniert wie beworben

+0

Es funktioniert gut, solange die Zeit ist einzigartig, aber es scheitert, wenn die "Mitte" -Zeit zwischen mehreren Zeilen wegen der Einschränkungen PropertyGt/Lt geteilt wird. Das Ändern in PropertyGe/Le funktioniert jedoch auch nicht. Verwenden Sie die Zeitwerte aus meiner Frage in Ihrer Probe und sehen Sie, was ich meine. Übrigens, dein Code hat mir sicherlich etwas Neues über Unteranfragen beigebracht :-) – HakonB

+0

bleh, vorübergehende Blindheit ließ mich die nicht-eindeutige Anforderung vermissen. Da es im Datensatz keine sequenzielle Reihenfolge gibt, kann ich keine Möglichkeit sehen, die erforderliche Antwort zu liefern – Jaguar