0

我正在寻找一种在给定主键和排序顺序的情况下检索 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。

是否可以在单个查询中检索条目(显然可以包括子查询)?时间是一个非唯一的列,因此多个条目具有相同的值,在此示例中,不可能以使其唯一的方式更改分辨率!

4

3 回答 3

1

“日期和主键之间没有直接关系”是指主键不是按顺序排列的吗?

然后我会这样做:

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);
于 2009-05-08T09:10:14.600 回答
0

使用 NHibernate 的 Criteria API 应该相对容易:

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

在这里,您listOfIds只是一个强类型整数列表,表示您要检索的条目的 id(整数 4242-5 到 4242+5 )。

当然,您也可以添加Expressions让您检索大于 4242-5 且小于 4242+5 的 Id。

于 2009-05-08T09:11:04.427 回答
0

Stefan 的解决方案确实有效,但使用单个选择和嵌套子查询存在更好的方法:

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 语法,但同样适用于早期版本,而不是使用表达式的限制。

我已经在测试应用程序上对此进行了测试,它可以像宣传的那样工作

于 2009-05-26T15:17:33.600 回答