Получить "окружающие" строки в запросе NHibernate - PullRequest
0 голосов
/ 08 мая 2009

Я ищу способ извлечения "окружающих" строк в запросе NHibernate по первичному ключу и порядку сортировки?

например. У меня есть таблица с записями журнала, и я хочу отобразить запись с первичным ключом 4242 и предыдущие 5 записей, а также следующие 5 записей, упорядоченных по дате (прямой связи между датой и первичным ключом нет). Такой запрос должен вернуть всего 11 строк (если мы не близки ни к одному из концов).

Таблица записей журнала может быть огромной, и получить все, чтобы понять ее, невозможно.

Существует ли такая концепция, как номер строки, которую можно использовать из NHibernate? Базовой базой данных будет SQlite или Microsoft SQL Server.

Отредактировано Добавлен образец

Представьте себе такие данные, как:

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

При запросе записи с первичным ключом 4242 мы должны получить строки 1237, 1238 и 4239 - 4247. Порядок по времени, Id.

Можно ли получить записи в одном запросе (который, очевидно, может включать подзапросы)? Время - неуникальный столбец, поэтому несколько записей имеют одинаковое значение, и в этом примере невозможно изменить разрешение таким образом, чтобы оно было уникальным!

Ответы [ 3 ]

1 голос
/ 08 мая 2009

«нет прямой связи между датой и первичным ключом» означает, что первичные ключи не в последовательном порядке?

Тогда я бы сделал это так:

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

Существует риск наличия нескольких предметов одновременно.


Редактировать

Это должно работать сейчас.

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 голосов
/ 26 мая 2009

Решение Стефана определенно работает, но лучший способ существует с использованием одного выбора и вложенных подзапросов:

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

Это синтаксис NHibernate 2.0, но то же самое относится и к более ранним версиям, где вместо Ограничений вы используете выражение.

Я проверил это на тестовом приложении, и оно работает как рекламируется

0 голосов
/ 08 мая 2009

Это должно быть относительно легко с API Критериев NHibernate:

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

Здесь ваш listOfIds - это просто строго типизированный список целых чисел, представляющих идентификаторы записей, которые вы хотите получить (целые числа от 4242-5 до 4242 + 5).

Конечно, вы также можете добавить Expressions, который позволит вам получать идентификаторы больше 4242-5 и меньше 4242 + 5.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...