37

我刚开始在我当前的项目中使用 NHibernate(使用 SQLite),而且我主要使用的是 NHibernate Query<>,因为我熟悉在 Linq 中编写数据库查询。

当我遇到一些更复杂的查询时,我做了一些研究QueryOver<>并认为应该优先考虑它,Query<>因为"QueryOver syntax is NH specific"。此外,似乎没有什么Query<>可以做却做不到QueryOver<>

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

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 进一步转换为实际数据库查询的“内部”(方法相关)查询吗?

4

2 回答 2

41

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

QueryOver 是 Criteria 的强类型版本,并且更加特定于 NHibernate。您在 ICriteria 中可以做的几乎所有事情都可以使用 QueryOver 来完成。在 ICriteria NH2 的黄金时代,您总是必须转换,因此这就是为什么现在您需要在链的末端转换回 int。

LINQ (Query) 是一种适用于 IQueryable 的标准查询方法,不需要对 NHibernate 的显式引用,并且可以被认为与 ORM 无关,因此遵循 linq 标准。正如您正确指出的那样,当您选择 customNumber 的结果时,您不需要强制转换为 int。

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

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

参考:权衡对比对比

于 2013-02-22T10:54:04.917 回答
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_

希望这会有所帮助

于 2013-02-22T17:02:33.877 回答