NHibernate Query<> 与 QueryOver<> 有啥区别?

Posted

技术标签:

【中文标题】NHibernate Query<> 与 QueryOver<> 有啥区别?【英文标题】:What is the difference between NHibernate Query<> vs QueryOver<>?NHibernate Query<> 与 QueryOver<> 有什么区别? 【发布时间】:2013-02-22 09:29:29 【问题描述】:

我在当前项目中刚开始使用 NHibernate(使用 SQLite),我主要使用 Query&lt;&gt;,因为我熟悉在 Linq 中编写 db 查询。

当我遇到一些更复杂的查询时,我对QueryOver&lt;&gt; 进行了一些研究,并认为它应该优于Query&lt;&gt;,因为“QueryOver 语法是 NH 特定的”。此外,似乎没有什么是Query&lt;&gt; 可以做到的,而QueryOver&lt;&gt; 却无法做到。

所以我开始相应地替换 Query&lt;&gt; 的所有用法。不久之后,我遇到了第一个“问题”,使用Query&lt;&gt; 似乎更方便。 示例(从表BillingDataEntity 中的列CustomNumber 中选择最大值):

int result = Session.Query<BillingDataEntity>().Select(x => x.CustomNumber).OrderByDescending(a => a).FirstOrDefault();
int result = Session.QueryOver<BillingDataEntity>().Select(x => x.CustomNumber).OrderBy(a => a.CustomNumber).Desc.Take(1).SingleOrDefault<int>();

我不喜欢的是需要将结果显式转换为 int 并且 Query 版本更易于阅读。我的查询完全错误,或者换句话说:有更好的方法吗?

我查看了生成的 SQL 输出:

NHibernate: select billingdat0_.CustomNumber as col_0_0_ from "BillingDataEntity" billingdat0_ order by billingdat0_.CustomNumber desc limit 1
NHibernate: SELECT this_.CustomNumber as y0_ FROM "BillingDataEntity" this_ ORDER BY this_.CustomNumber desc limit @p0;@p0 = 1 [Type: Int32 (0)]

我到底在看什么?这是 NHibernate 进一步转换为实际数据库查询的“内部”(方法相关)查询吗?

【问题讨论】:

【参考方案1】:

*** 上有很多关于 QueryOver 与 Query 的答案,但简而言之:-

QueryOver 是 Criteria 的强类型版本,并且更 NHibernate 特定的。您在 ICriteria 中可以做的几乎所有事情都可以 用 QueryOver 完成。在 ICriteria NH2 的黄金时期,您一直拥有 投,因此这就是为什么现在你需要在结束时投 链接回一个 int。

LINQ (Query) 是一种适用于 IQueryable 的标准查询方法 不需要对 NHibernate 的显式引用,可以考虑 更多的 ORM 不可知,因此遵循 linq 标准。正如你 正确地指出你不需要像你一样转换为 int 在结果中选择 customNumber。

如果生成的 SQL 非常不同,我会对您的简单示例感到非常惊讶。

我是QueryOver 的忠实粉丝,但随着 Linq 提供程序变得越来越成熟,我 95% 的查询都使用 Query,但对于某些 Nhibernate 特定的东西,我又求助于 QueryOver。无论哪种方式,我都建议使用分析工具来查看您可以接受的内容。

参考:Tradeoffs 或 versus 和 versus

【讨论】:

我不确定您是否可以直接回答您的第一个问题,因为我的回答指出 QueryOver 基于 ICiteria 和 this is the way it has to be done you are doing it correctly。要查看生成的 SQL,我会使用像 NHProf 这样的商业工具,因为它是最好的。没有直言不讳的意思,HTH 澄清了我给出的答案。 另外,Query&lt;T&gt; 返回一个IQueryable,它是一个IEnumerable,所以非常方便。 @Rippo:第二个和第三个链接指向同一个问题【参考方案2】:

关于您的 QueryOver 版本,我会写:

int result = Session.QueryOver<BillingDataEntity>()
               .Select(Projections.Max<BillingDataEntity>(x => x.CustomNumber))
               .SingleOrDefault<int>();

它看起来很可读,生成的 SQL 将类似于:

SELECT max(this_.CustomNumber) as y0_ FROM "BillingDataEntity" this_

希望这会有所帮助

【讨论】:

以上是关于NHibernate Query<> 与 QueryOver<> 有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章

LINQ Fluent NHIBERNATE .Contains() 在 QueryOver<> 中不起作用,但在 Query<> 中起作用

在NHibernate查询中实现条件的更好方法是什么?

NHibernate,如何读取 NamedQuery 结果元数据?

NHibernate QueryOver 两次加入一个集合

NHibernate .SelectList() 与 C# 中的 List<string>

NHibernate IQueryable 似乎不会延迟执行