我正在寻找一种在给定主键和排序顺序的NHibernate查询中检索“周围”行的方法吗?
E.g。我有一个包含日志条目的表,我想显示带有主键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。
是否可以在单个查询中检索条目(显然可以包含子查询)?时间是一个非唯一列,因此多个条目具有相同的值,在此示例中,无法以使其唯一的方式更改分辨率!
答案 0 :(得分: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);
答案 1 :(得分: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。
答案 2 :(得分: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语法,但同样适用于早期版本,而不是使用Expression的限制。
我已经在测试应用程序上对此进行了测试,它的工作方式与广告一致