Frage

Ich bin auf der Suche nach einem Weg, um die „Umgebung“ Zeilen in einer NHibernate-Abfrage einen Primärschlüssel und eine Sortierreihenfolge gegeben zurückzuholen?

z. Ich habe eine Tabelle mit Protokolleinträgen und ich möchte mit Primärschlüssel 4242 und die letzten 5 Einträge sowie die folgenden 5 Einträge nach Datum geordnet den Eintrag anzuzeigen (es gibt keine direkte Beziehung zwischen Datum und Primärschlüssel). Eine solche Abfrage 11 Zeilen insgesamt zurückgeben soll (solange wir entweder Ende nicht in der Nähe sind).

Der Protokolleintrag Tabelle kann sehr groß sein und Abrufen alle, es herauszufinden ist nicht möglich.

Gibt es ein solches Konzept als Zeilennummer, die von innen NHibernate verwendet werden kann? Die zugrunde liegende Datenbank wird entweder gehen SQlite oder Microsoft SQL Server sein.

Edited hinzugefügt Probe

Stellen Sie Daten wie folgt:

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

Beim Anfordern der Eingabe mit Primärschlüssel 4242 sollen wir die Reihen 1237, 1238 und 4239 bis 4247 Die Reihenfolge von Zeit erhalten ist, Id.

Ist es möglich, die Einträge in einer einzigen Abfrage abzurufen (die Unterabfragen können offensichtlich sind)? Die Zeit ist eine nicht eindeutige Spalte so mehr Einträge haben den gleichen Wert und in diesem Beispiel ist es nicht möglich, die Auflösung in eine Art und Weise zu ändern, die es einzigartig macht!

War es hilfreich?

Lösung

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

Dann würde ich es tun, wie folgt aus:

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 nun 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);

Andere Tipps

Dies sollte relativ einfach mit NHibernate Criteria API sein:

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 4242-5 bis 4242 + 5).

abgerufen werden sollen

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

Stefan Lösung funktioniert auf jeden Fall aber bessere Möglichkeit existiert eine einzelne auswählen und verschachtelte Unterabfragen 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 verwendet werden.

Ich habe dies auf einer Testanwendung getestet und es funktioniert wie beworben

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top