程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> NHibernate 2.0.1下實現SQL2000真分頁

NHibernate 2.0.1下實現SQL2000真分頁

編輯:關於.NET

最近用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");
            }

            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();
        }
    }

這個類繼承自原 NHibernate 的 mssql2000方言類 重寫了 SupportsLimitOffset 屬性 返回 true 讓 NHibernate 支持 offset

重寫了 GetLimitString 方法 使用 內存變量表的方式進行數據分頁 前提是 hql 語句裡必須帶有主鍵排序字段 主鍵必須是 自動增長

下面介紹如何使用這個類來替換 NHibernate 下的原mssql2000方言:

在NHibernate配置文件裡的找到 <property name="dialect">NHibernate.Dialect.MsSql2000Dialect</property>< /P>

替換成 <property name="dialect">myMsSql2000Dialect類的命名空間 .myMsSql2000Dialect</property>

哪位高人有更好的實現方式的話 別忘了共享給我下

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved