当前位置:主页   - 电脑 - 网站开发 - ASP.Net
NHibernate 2.0.1 下实现SQL2000真分页
来源:网络   作者:   更新时间:2012-08-18
收藏此页】    【字号    】    【打印】    【关闭

  最近用NHibernate做个项目 由于数据库用的是mssql2000 NHibernate 对mssql2000的分页查询支持的不是很好 于是自己动手实现一个mssql2000方言

  原 NHibernate.Dialect 命名空间下的mssql2000的方言类 MsSql2000Dialect 里的 GetLimitString 方法 如下:

  public override SqlString GetLimitString(SqlString querySqlString, int offset, int limit)
  {
   if (offset > 0)
   {
    throw new NotSupportedException("SQL Server does not support an offset");
   }

   /*
    * "SELECT TOP limit rest-of-sql-statement"
    */

   return querySqlString.Insert(GetAfterSelectInsertPoint(querySqlString), " top " + limit.ToString());
  }

  看上面这段代码大家都知道这种分页方式的性能有多么的差 下面我把我自己实现的方言类代码贴出来

public class mySqlServer2000Dialect : MsSql2000Dialect
    {
        private static int GetFromIndex(SqlString querySqlString)
        {
            string subselect = querySqlString.GetSubselectString().ToString();
            int fromIndex = querySqlString.IndexOfCaseInsensitive(subselect);
            if (fromIndex == -1)
            {
                fromIndex = querySqlString.ToString().ToLowerInvariant().IndexOf(subselect.ToLowerInvariant());
            }
            return fromIndex;
        }


        private static string RemoveSortOrderDirection(string sortExpression)
        {
            // Drop the ASC/DESC at the end of the sort expression which might look like "count(distinct frog.Id)desc" or "frog.Name asc".
            return Regex.Replace(sortExpression.Trim(), @"()|s)(?i:asc|desc)$", "$1").Trim();
        }

        public override bool SupportsLimitOffset
        {
            get
            {
                return true;
            }
        }

        public override NHibernate.SqlCommand.SqlString GetLimitString(SqlString querySqlString, int offset, int limit)
        {
            if (offset == 0)
            {
                return base.GetLimitString(querySqlString, offset, limit);
            }

            SqlString myQuery = new SqlString(RemoveSortOrderDirection(querySqlString.ToString().ToLower()));

            int orderIndex = myQuery.LastIndexOfCaseInsensitive(" order by ");

            if (orderIndex <= 0)
            {
                throw new NotSupportedException("must specify 'order by' statement to support limit operation with offset in SqlServer2000");
    r       }

            string orderBy = myQuery.Substring(orderIndex).ToString().Trim();

            string[] sortExpressions = myQuery.Substring(orderIndex).ToString().Trim().Substring(9).Split(',');

            int fromIndex = GetFromIndex(myQuery);

            SqlString from = myQuery.Substring(fromIndex, orderIndex - fromIndex).Trim();

            string fromAsName = from.ToString().Substring(from.ToString().IndexOf(' ', 5)).Trim();

            SqlString select = myQuery.Substring(0, fromIndex);

            int PageSize = limit - offset;

            SqlStringBuilder result = new SqlStringBuilder();

            result.Add("declare @indextable table(id int identity(1,1),nid int) set rowcount " + limit.ToString());
           
            result.Add(" insert into @indextable(nid) select");

            result.Add(" " + RemoveSortOrderDirection(sortExpressions[0]).Replace(fromAsName,"t") + " " + from.ToString().Replace(fromAsName,"t") + " " + orderBy.Replace(fromAsName,"t") + " desc ");

            result.Add(" " + select.ToString() + " " + from.ToString() + ",@indextable a where " + RemoveSortOrderDirection(sortExpressions[0]) + " = a.nid and a.[id] between " + (offset + 1).ToString() + " and " + limit.ToString());

            return result.ToSqlString();
        }
    }

其它资源
来源声明

版权与免责声明
1、本站所发布的文章仅供技术交流参考,本站不主张将其做为决策的依据,浏览者可自愿选择采信与否,本站不对因采信这些信息所产生的任何问题负责。
2、本站部分文章来源于网络,其版权为原权利人所有。由于来源之故,有的文章未能获得作者姓名,署“未知”或“佚名”。对于这些文章,有知悉作者姓名的请告知本站,以便及时署名。如果作者要求删除,我们将予以删除。除此之外本站不再承担其它责任。
3、本站部分文章来源于本站原创,本站拥有所有权利。
4、如对本站发布的信息有异议,请联系我们,经本站确认后,将在三个工作日内做出修改或删除处理。
请参阅权责声明