zoukankan      html  css  js  c++  java
  • SQLite 使用NHibernate分页的BUG

    今天因为sqlite分页的原因,浪费了几个小时!

    sqlite从第三个分页开始,只显示第二页的数据!

    在检查自己代码无误的情况下,开始怀疑NHibernate处理sqlite处理分页有问题!

    把数据库换成ms sql,发现分页没有问题!

    还好,这时候找了一篇文章,解答了我的疑惑!

    不同的是:我用的是NHibernate-2.0.1.GA正式版!

    探索的路,真的很难!基于这个原因!试试用NHibernate2.1GA版本,反正spring.net 1.3已经支持了。

    http://3rgb.com/entry/bug_of_NHibernate_with_SQLite

    原文如下:

    先说明,我用的是NHibernate2.0.1-GA版本,测试版的,并且以下出现的问题已经被BUG TRACKER记录并修正,但是NH站上提供的BIN也好,源SOURCE也好,都还没有更新。

    具体情况:N3C用的是SQLite3,然后使用上述的NHibernate进行数据库操作,在进行分页的时候,只能正确分出第一页和第二页,从第三页开始往后,只显示第二页的内容。

    SQLite中分页取数据的方面是SQL语句后面加limit startRow,offset,如果是第一页,直接就是limit offset;比如我每页显示10条,正常情况下是,第一页limit 10,第二页limit 10,10,第三页limit 20,10,第四页limit 30,10。。。但是在上述版本的NHibernate所产生的SQL语句中,从第三页开始变成limit 10,20,第四页limit 10,30如此类推;原因在于NH在组装SQL语句的时候,把start和offset给弄反了。而在输出数据时,由于设置了offset为10,后面的情况就变成了,取从第10条记录开始的20,30,40,50。。。。第记录,然后再只返回前10条;这样一来,越往后分页效率越差,数据库压力越大不说,从第三页开始往后,我们只能看到第二页的10条记录了。

    所以,要么等NH官方修复这个BUG,要么就自己改源SOURCE自己编译个新的DLL吧。

    具体修改方法:

    Index: SQLiteDialect.cs
    ===================================================================
    --- SQLiteDialect.cs (revision 3862)
    +++ SQLiteDialect.cs (working copy)
    @@ -179,14 +179,15 @@
        SqlStringBuilder pagingBuilder = new SqlStringBuilder();
        pagingBuilder.Add(querySqlString);
    pagingBuilder.Add(" limit ");
    - pagingBuilder.Add(limit.ToString());
    -
    +
    if (offset > 0)
    {
    + pagingBuilder.Add(offset.ToString());
    pagingBuilder.Add(", ");
    - pagingBuilder.Add(offset.ToString());
    }

    + pagingBuilder.Add(limit.ToString());
    +
    return pagingBuilder.ToSqlString();
    }
      }

    上面的代码来自于http://jira.nhibernate.org/secure/attachment/12560/SQLiteDialect-FixPaging.patch,其中前面标“-”号的意思是要删掉的行,加“+”号的是新加的代码。修改之后,就编译一个新的NHibernate.dll出来吧。

    【后记】

    把 nhibernate转换成2.1GA版本后,分布bug消失。

    原有代码只改动了一处:

                #region 1.2时可用
                //recordCount = Convert.ToInt32(criteria.SetProjection(Projections.RowCount()).UniqueResult());
                //消除,便于重用
                //以下在1.3版本报错!
                //criteria.SetProjection(null);
                #endregion

                #region 1.3版本对:SetProjection有改变
                //        * ICriteria.SetProjection now takes a params array of projections, instead of a single projection
                //Only a breaking change if you are implementing ICriteria, there is full source code compatability
                //Projections.ProjectionList():create a new projection list,每次查询都是新建一个ProjectionList
                //这样就不存在要消除Projection设置的问题!
                recordCount = Convert.ToInt32(criteria.SetProjection(Projections.ProjectionList()
                                                                              .Add(Projections.RowCount())).UniqueResult());

                #endregion

  • 相关阅读:
    aptget 的使用
    NetScaler
    This Android SDK requires Android Developer Toolkit version 10.0.0 or above
    创建menu的时候为什么要用Menu.FIRST常量?
    SQLServer中char、varchar、nchar、nvarchar的区别
    HTTP响应头信息和请求头信息详解
    第十一章 常见字词误用的情形 《英语科技写作(文法与修辞原则)》by 方克涛
    Random类不能产生随机数的情况测试
    将Web Services封装到一个dll
    在DataTable中查找
  • 原文地址:https://www.cnblogs.com/goldarch/p/1731144.html
Copyright © 2011-2022 走看看