【问题标题】:Get "surrounding" rows in NHibernate query在 NHibernate 查询中获取“周围”行
【发布时间】:2009-05-08 08:56:25
【问题描述】:

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

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

【问题讨论】:

    标签: sql-server nhibernate sqlite hql


    【解决方案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);
    

    【讨论】:

    • 我想只要排序在包含唯一值的列上,这将起作用。我可能需要对不同的列进行排序,因此保留序列列是行不通的。我正在寻找一种 rownum 解决方案,以应对需要对非唯一列进行排序的情况,因此欢迎更多想法:-)
    • 好的,完善一下。请参阅新部分。
    【解决方案2】:

    使用 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。

    【讨论】:

    • 我将如何获得声望? :) 当我在 5 分钟内发布答案时,其他人也发布了答案。
    • 金钱就是如此。如果你拥有它,你就会得到它。人们更频繁地投票选出具有高声誉的成员的答案。人生是不公平的。但不要在意,提供好的答案总是值得赞赏的,应该是主要意图。
    • 正如 Stefan 上面提到的,日期和主键之间没有直接关系,因此仅按主键选择是行不通的。我可能有一个解决方案,我还需要按使主键解决方案无效的类别进行过滤。
    • 啊是的..对不起..我应该在发布答案之前阅读这个问题。给斯特凡钱! :)
    【解决方案3】:

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

    我已经在一个测试应用程序上对此进行了测试,它的工作原理与宣传的一样

    【讨论】:

    • 只要时间是唯一的,它就可以很好地工作,但是当由于 PropertyGt/Lt 限制而在多行之间共享“中间”时间时它会失败。但是,仅更改为 PropertyGe/Le 也不起作用。尝试在您的示例中使用我的问题中的时间值,看看我的意思。顺便说一句,你的代码确实教会了我一些关于子查询的新知识:-)
    • bleh,暂时失明让我错过了非唯一要求。由于数据集中没有顺序排序,我看不到任何方法来提供所需的答案
    猜你喜欢
    • 1970-01-01
    • 2011-04-19
    • 1970-01-01
    • 2023-04-04
    • 1970-01-01
    • 2014-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多