nHibernate 生成了这个奇怪的 SQL; SQLS 是不是按原样使用它?

Posted

技术标签:

【中文标题】nHibernate 生成了这个奇怪的 SQL; SQLS 是不是按原样使用它?【英文标题】:nHibernate generated this odd bit of SQL; did SQLS consume it as is?nHibernate 生成了这个奇怪的 SQL; SQLS 是否按原样使用它? 【发布时间】:2018-05-14 08:46:15 【问题描述】:

由于以下 LINQ:

plans
  .Where(p => p.Attributes.Any(a => a.Attribute.Product.Type == callType) && 
    call.StartTime < p.EndDate.GetValueOrDefault(System.Data.SqlTypes.SqlDateTime.MaxValue.Value) &&
    call.StartTime > p.StartDate.GetValueOrDefault(System.Data.SqlTypes.SqlDateTime.MinValue.Value))

计划类似于手机计划。假设国际电话的基本价格为每分钟 1 美元,并且该合同的开始和结束时间为空,因为它是基本价格。为 12 月制定了一个特殊计划,从 1 日开始,到该月的最后一天结束。该计划应该覆盖基础(稍后会使用.OrderBy endtime-starttime [即计划越短,覆盖性越强] + .First,但这对我来说现在并不感兴趣)但它应该只适用于 12 月拨打的电话,因此这两个条款确保我们只寻找支持电话类型的计划,并且开始/结束日期跨越拨打电话的时间

根据 nHibernate 的输出窗口调试,这将转换为以下 SQL:

and 
  (exists 
    (
      ..blah blah blah.. 
      where product7_.Type=?
    )
  ) and ?<coalesce(plan4_.EndDate, ?) and ?>coalesce(plan4_.StartDate, ?)

我得到 EXISTS (blahblahblah),因为它源自 p.Any(),但尖括号中的时髦 SQL 是什么?

看起来) and ?&lt;coalesce(plan4_.EndDate, ?) and ?&gt;coalesce(plan4_.StartDate, ?) 应该是(在常规 SQL 语法中)

and call.starttime BETWEEN COALESCE(plan.StartDate, '1753-01-01') AND COALESCE(plan.EndDate, '9999-12-31')

SQLServer 是否使用它作为 nHibernate 的输出,或者 nHibernate 的其他部分负责将其扩展为更像我的“常规”SQL 的东西? (nhibernate运行在sqlserver2008模式,但是目标是azure)

【问题讨论】:

myNullableDate.GetValueOrDefault(someDateValue) 在可空日期,如果 myNullableDate.HasValue,则返回 myNullableDate.Value,如果可空日期为空,则返回 someDateValue 值。 COALESCE 返回遇到的第一个非空参数,从左到右读取 我不一定跟踪到达数据库的实际 SQL;我使用拦截器public class SqlStatementInterceptor : EmptyInterceptor public override global::NHibernate.SqlCommand.SqlString OnPrepareStatement(global::NHibernate.SqlCommand.SqlString sql) Trace.WriteLine(sql.ToString()); return sql; 跟踪 nHibernate 准备的 sql 您是否能够运行跟踪并查看提交到数据库的内容? 我不确定;这个项目已经是一个巨大的陌生领域,因为我不在最初的开发团队中,我们的其他东西都没有使用 nH/castlewindsor.. 也许更简单的假设是 nH 在它之后对 SQL 字符串进行了更多的操作完成Prepareing 它,因为我几乎 100% 确定 SQLServer 不会对此做任何事情,即使它看起来有点像参数化查询(odbc 风格,记住,而不是 sqlserver @param 风格)。也许闯入拦截器并介入会让我看到它的其他地方 blog.sqlauthority.com/2009/01/07/… 可能会有所帮助 【参考方案1】:

答案是尖括号中没有时髦的 SQL :)

仔细观察,这些是查询中的&lt;(小于)和&gt;(大于)运算符,SQL 也支持这些运算符。 缺少空格让您感到困惑。

? 符号是查询中位置参数的常用占位符,因为这些参数不与 SQL 文本内联发送(在本例中,call.StartTime 的值和最大/最小日期值)。

你可以理解为:

and :startTime < coalesce(plan4_.EndDate, :sqlTimeMaxValue) and :startTime > coalesce(plan4_.StartDate, :sqlTimeMinValue)

希望有帮助!

【讨论】:

谢谢弗雷迪;我认为它需要第二双眼睛才能看到这种解释——看不到代码的 sql!

以上是关于nHibernate 生成了这个奇怪的 SQL; SQLS 是不是按原样使用它?的主要内容,如果未能解决你的问题,请参考以下文章

NHibernate bug sql 生成器

NHibernate HQL 生成器支持 SQL Server 2016 时态表

我怎样才能让 NHibernate 只生成 SQL 而不执行它?

ORM篇——使用NHibernate配置对象实体的一些小问题

NHibernate 在 Nunit 测试中的奇怪失败

将原生 SQL where 子句应用于实体的 Nhibernate 查询