NHibernate第二层缓存,自定义查询,SQL方言

NHibernate第二层缓存,自定义查询,SQL方言,nhibernate,second-level-cache,Nhibernate,Second Level Cache,我得到了NH和FNH的主干版本。当我尝试添加二级缓存时,NHibernate的某些部分忘记了所选的SQL方言 初始配置: var cfg = Fluently.Configure() .Database(MsSqlConfiguration.MsSql2008 .ConnectionString(connectionString) .DefaultSchema("dbo") .UseReflectionOptimizer() .Mappings(m =&

我得到了NH和FNH的主干版本。当我尝试添加二级缓存时,NHibernate的某些部分忘记了所选的SQL方言


初始配置:

var cfg = Fluently.Configure()
  .Database(MsSqlConfiguration.MsSql2008
    .ConnectionString(connectionString)
    .DefaultSchema("dbo")
    .UseReflectionOptimizer()    
  .Mappings(m => ................);
自定义查询:

var sql = @"with Foo(col1,col2,col3)
              as (select bla bla bla...)
            Select bla bla bla from Foo";

list = Session.CreateSQLQuery(sql)
  .AddEntity("fizz", typeof(Fizz))
  .SomethingUnimportant();
当我将配置更改为:

var cfg = Fluently.Configure()
  .Database(MsSqlConfiguration.MsSql2008
    .ConnectionString(connectionString)
    .DefaultSchema("dbo")
     .UseReflectionOptimizer()
     .Cache(c=>c
       .UseQueryCache()
         .ProviderClass<HashtableCacheProvider>())
       .ShowSql())
     .Mappings(m => ................);
看起来是
.SetMaxResults(123)
导致了这种情况。幸运的是,我可以解除对该查询的绑定


希望这能解决这个问题。

正如我预测的那样-取消绑定选择是可以接受的解决方法


删除了
SetMaxResults
,它可以正常工作。

只是在使用类似的带有WITH子句的查询时遇到了同样的问题

不幸的是,我的查询填充了一个带有分页的网格,因此我必须保留SetMaxResults

我的解决方案是使用派生表重写:

var sql = @"with Foo(col1,col2,col3)
              as (select x1, x2, x3 from x join y blabla)
            Select col1, col2, col3 from Foo
            join B on B.col1 = Foo.col1";
变成

var sql = @"Select col1, col2, col3 from 
           (select x1 as col1, x2 as col2, x3 as col3 
            from x join y blabla) as Foo
           join B on B.col1 = Foo.col1";
只是为了允许NHibernate在“select”字符串之后插入“TOP x”字符串(从开始的6个字符)。。。无可奉告:(

T

我遇到了类似的问题(删除
SetMaxResults
也有帮助,但我需要分页),并发现以下NHibernate配置属性导致了此错误:

<property name="use_sql_comments">true</property>
true
这当然是一个bug,因为
GetAfterSelectInsertPoint
方法没有考虑SQL查询前面可能有SQL注释


只要将
use\u sql\u comments
属性设置为
false
,问题就消失了。

在查找查询中插入TOP子句(GetAfterSelectInsertPoint)的位置的例程中,似乎有一些奇怪的错误,正如Sandor所说的。您可以直接在nh source中修复它(我实际上修补了我在项目中使用的2.1版本,您可以)。因此,如果您确实需要启用带有use_sql_comments的注释,您可以:)

我使用Alkampfer的解决方案修复了该错误,但我创建了自己的sql方言,而不是直接修补NHibernate源代码:

public class Sql2008DialectWithBugFixes : MsSql2008Dialect
{
    public override SqlString GetLimitString(SqlString querySqlString, int offset, int last)
    {
        if (offset == 0)
        {
            return querySqlString.Insert(GetAfterSelectInsertPoint(querySqlString), " top " + last);
        }

        return base.GetLimitString(querySqlString, offset, last);
    }

    private static int GetAfterSelectInsertPoint(SqlString sql)
    {
        Int32 selectPosition;

        if ((selectPosition = sql.IndexOfCaseInsensitive("select distinct")) >= 0)
        {
            return selectPosition + 15; // "select distinct".Length;

        }
        if ((selectPosition = sql.IndexOfCaseInsensitive("select")) >= 0)
        {
            return selectPosition + 6; // "select".Length;
        }

        throw new NotSupportedException("The query should start with 'SELECT' or 'SELECT DISTINCT'");
    }
}

我在从1.2升级到3.2时遇到了这个问题(我知道,大跳跃是吗?)

在我的例子中,问题是hql中select语句前面有一个前导空格,例如String hql=“select”

使用SQL2005方言时,会出现“System.NotSupportedException:查询应以“SELECT”…”消息开头的情况

解决办法是

  • 创建一个失败的单元测试,一个好的测试驱动开发人员 应该:)
  • 从“select…”语句中删除前导空格
  • 构建并运行单元测试

  • 我们在升级到NHibernate版本3.3时遇到了这个问题,但原因不同…空白。我们有很多sql字符串如下所示:

    var sql = @"
    select col1 from MyTable";
    
    或:

    这导致了“查询应以'SELECT'或'SELECT DISTINCT'开头”错误,因为NHibernate在验证字符串之前没有修剪字符串

    我们创建了一种新的方言,首先修剪字符串以解决此问题:

    public class Sql2008DialectCustom : MsSql2008Dialect
    {
      public override SqlString GetLimitString(SqlString queryString, SqlString offset, SqlString limit)
      {
        var trimmedQueryString = queryString.Trim();
        return base.GetLimitString(trimmedQueryString, offset, limit);
      }
    }
    

    真不敢相信它又发生了!
    var sql = @" select col1 from My Table";
    
    public class Sql2008DialectCustom : MsSql2008Dialect
    {
      public override SqlString GetLimitString(SqlString queryString, SqlString offset, SqlString limit)
      {
        var trimmedQueryString = queryString.Trim();
        return base.GetLimitString(trimmedQueryString, offset, limit);
      }
    }