Asp.Net(C#)+Sql Server三層架構下數據存取方案

Asp.Net(C#)+Sql Server三層架構下數據存取方案

引言:

參與了一個大型社區程序的開發,現在將相關開發經驗陸續總結出來,和大家探討一下。本節主要想與大家探討一種數據讀取方案:集合類代替直接從數據庫中獲取的DataSet,主要好處就是可以解決Sql Server吞吐量的瓶頸問題。一般小數量的程序不會有問題,但數據以十萬百萬條計的時候,數據庫的吞吐量的限制就會表現的比較明顯。這裏的解決方案其實也就是把海量數據信息分成一條條取出,以頻繁取庫的代價解決瓶頸限制,其實也就是把數據庫服務器的負擔讓WEB服務器分擔了。閒話少說,進入正題,們的例子還是社區程序中的一個配置表的讀取,們就是要據一定條件來從數據庫中獲取數據。

一、數據庫設計:

 

ScoreSetting   積分設置表

Key:   ScoreSettingID

Field name

Type

Length

Default

Description

ScoreSettingID

int

4

0

ScoreSettingID(自動編號)

FunctionID

int

4

0

 功能ID

OperationID

int

4

0

 操作ID

RoleTypeID

int

4

0

 身份ID

BBSTypeID

int

4

0

 論壇類別ID

Score

int

4

0

 積分數

BB

int

4

0

 幣幣數

BuyType

Int

4

0

  購買類型

FunctionState

int

4

0

 0:否,1:是,2:購買


存儲過程:

/**********************************

功能:據一定條件讀取功能記錄

作者:Rexsp

創建日期:2004-01-13

修改者:

修改日期:

**********************************/

ALTER PROCEDURE GetScoreSetting

(  

    @ScoreSettingID INT=-1,                    ---設置ID

     @FunctionID INT=-1,                        ---功能ID

     @OperationID INT=-1,                       ---操作ID

     @RoleTypeID INT=-1,                        ---角色類型

     @BBSTypeID INT=-1,                         ---版塊類型

     @Score INT=-1,                             ---積分設置  

     @BB INT=-1,                                ---幣幣設置

     @BuyType INT=-1,                           ---購買類型 0:不是購買類型 1:一次性購買 2:反覆購買

     @FunctionState INT=-1                      ---功能狀態

)

AS

SET NOCOUNT ON

DECLARE @strSQL NVARCHAR(1000)

SET @strSQL = 'SELECT * FROM [ScoreSetting] WHERE @ckScoreSettingID = @ckScoreSettingID'

--- Add KeyWords Begin ---

IF @ScoreSettingID<> -1

     BEGIN

         SET @strSQL = @strSQL + ' AND ScoreSettingID= @ckScoreSettingID'

     END

IF @FunctionID<> -1

     BEGIN

         SET @strSQL = @strSQL + ' AND FunctionID= @ckFunctionID'

     END

IF @OperationID<>-1

     BEGIN

         SET @strSQL = @strSQL + ' AND OperationID = @ckOperationID'

     END

IF @RoleTypeID<>-1

     BEGIN

         SET @strSQL = @strSQL + ' AND  RoleTypeID = @ckRoleTypeID'

     END

IF @BBSTypeID<>-1

     BEGIN

         SET @strSQL = @strSQL + ' AND  BBSTypeID = @ckBBSTypeID'

     END

IF @Score<>-1

     BEGIN

         SET @strSQL = @strSQL + ' AND  Score = @ckScore'

     END

IF @BB<>-1

     BEGIN

         SET @strSQL = @strSQL + ' AND  BB= @ckBB'

     END

IF @BuyType<>-1

     BEGIN

         SET @strSQL = @strSQL + ' AND  BuyType= @ckBuyType'

     END

IF @FunctionState<>-1

     BEGIN

         SET @strSQL = @strSQL + ' AND  FunctionState= @ckFunctionState'

     END

--- Add Where Key Word ---

--- Run SQL Begin ---

EXECUTE sp_executesql @strSQL,

         N'   @ckScoreSettingID INT,

              @ckFunctionID INT,

              @ckOperationID INT,

              @ckRoleTypeID INT,

              @ckBBSTypeID INT,

              @ckScore INT,

              @ckBB INT,

              @ckBuyType INT,

              @ckFunctionState INT',

              @ckScoreSettingID=@ScoreSettingID,

              @ckFunctionID=@FunctionID,

              @ckOperationID = @OperationID,

              @ckRoleTypeID = @RoleTypeID,

              @ckBBSTypeID  = @BBSTypeID,

              @ckScore = @Score,

              @ckBB = @BB,

              @ckBuyType = @BuyType,

              @ckFunctionState = @FunctionState

--- Run SQL End ---

 

一點說明:

此存儲過程會據數據層的類有沒有傳遞相應的參數值進來而動態創建查詢語句,然後用系統自帶的存儲過程執行sql語句,用系統存儲過程執行sql語句的好處是可以自動轉義字符。而動態創建查詢語句的好處,就非常大了,這會省下們寫很多種條件判斷,尤其是對那些字段比較多的表來講,一個排列組合下來的情況太多了,而利用存儲過程動態創建sql語句所作的判斷數和字段數基本上是一致的,這裏會給入參賦初始值,如果不等於初始值就說明數據層類有傳遞參數進來,這樣就加上相應條件字符的查詢條件。

一、 數據層類:

using System;

using System.Collections;

using System.Data;

using System.Data.SqlClient;

using Town.Data;

using Town.Log;

 

namespace Town.Com

{

     /// <summary>

     /// 功能:積分設置集合類

     /// 作者:Rexsp

     /// 創建日期:2004-01-14

     /// 修改者:

     /// 修改日期:

     /// </summary>

     public class ScoreSettingCollection

     {

         #region 私有成員

         private ArrayList members;

         #endregion

 

         #region 構造函數

         /// <summary>

         /// 構造函數

         /// </summary>

         public ScoreSettingCollection()

         {

         }

         #endregion

 

         #region 公共屬性

         /// <summary>

         /// Operation對象的個數

         /// </summary>

         public int Count

         {

              get

              {

                   if( members != null )

                       return members.Count;

                   else

                       return 0;

              }

         }

         #endregion

 

         #region 索引

         /// <summary>

         /// 索引

         /// </summary>

         public ScoreSetting this[int index]

         {

              get

              {

                   if ( members != null )

                       return (ScoreSetting)( members[index] );

                   else

                       return null;

              }

         }

         #endregion

 

         #region 私有方法

         /// <summary>

         /// 添加Operation到OperationCollection集合

         /// </summary>

         private void Add(ScoreSetting scoreSetting)

         {

              if ( members == null )

                   members = new ArrayList();

              members.Add( scoreSetting );

         }

         #


  #region 公共方法

         /// <summary>

         /// 據不同條件取得積分設置

         /// </summary>

         /// <param name="functionID">功能ID</param>

         /// <param name="operationID">操作ID</param>

         /// <param name="roleTypeID">角色ID</param>

         /// <param name="bBSTypeID">版塊類型DI</param>

         /// <param name="score">積分</param>

         /// <param name="bB">幣幣</param>

         /// <param name="buyType">購買類型</param>

         /// <param name="functionState">功能狀態</param>

         /// <returns></returns>

         public bool GetSpecialInfo(int functionID,int operationID,int roleTypeID,int bBSTypeID,int score,int bB,int buyType,int functionState)

         {

              SqlDataAdapter dataAdapter = null;

              Database data = new Database("Town");

              #region 創建參數

              ArrayList sqlParameterList=new ArrayList();

              if(functionID!=-1)

                   sqlParameterList.Add(data.MakeInParam("@FunctionID",  SqlDbType.Int, 4,    functionID));

              if(operationID!=-1)

                   sqlParameterList.Add(data.MakeInParam("@OperationID",  SqlDbType.Int, 4,   operationID));

              if(roleTypeID!=-1)

                   sqlParameterList.Add(data.MakeInParam("@RoleTypeID",  SqlDbType.Int, 4,    roleTypeID));

              if(bBSTypeID!=-1)

                   sqlParameterList.Add(data.MakeInParam("@BBSTypeID",  SqlDbType.Int, 4,     bBSTypeID));

              if(score!=-1)

                   sqlParameterList.Add(data.MakeInParam("@Score",  SqlDbType.Int, 4,    score));

              if(bB!=-1)

                   sqlParameterList.Add(data.MakeInParam("@BB",  SqlDbType.Int, 4,  bB));

              if(buyType!=-1)

                   sqlParameterList.Add(data.MakeInParam("@BuyType",  SqlDbType.Int, 4,  buyType));

              if(functionState!=-1)

                   sqlParameterList.Add(data.MakeInParam("@FunctionState",  SqlDbType.Int, 4, functionState));

 

              SqlParameter[] prams= new SqlParameter[sqlParameterList.Count];

              for( int i=0;i<sqlParameterList.Count;i++)

              {

                   prams[i]=(SqlParameter)sqlParameterList[i];

              }

              #endregion

              try

              {

                   data.RunProc("GetScoreSetting", prams, out dataAdapter);

                   DataSet dataSet = new DataSet();

                   dataAdapter.Fill(dataSet,"table");

                   dataAdapter.Dispose();

                   if(dataSet.Tables["table"].Rows.Count == 0)

                   {

                       dataSet.Clear();

                       dataSet.Dispose();

                       return false;

                   }

                   else

                   {

 

                       foreach(DataRow dr in dataSet.Tables["table"].Rows)

                       {

                            ScoreSetting SS = new ScoreSetting();

                            SS.ID= Int32.Parse(dr["ScoreSettingID"].ToString().Trim());

                            SS.FunctionID= Int32.Parse(dr["FunctionID"].ToString().Trim());

                            SS.OperationID= Int32.Parse(dr["OperationID"].ToString().Trim());

                            SS.RoleTypeID= Int32.Parse(dr["RoleTypeID"].ToString().Trim());

                            SS.BBSTypeID= Int32.Parse(dr["BBSTypeID"].ToString().Trim());

                            SS.Score= Int32.Parse(dr["Score"].ToString().Trim());

                            SS.BB= Int32.Parse(dr["BB"].ToString().Trim());

                            SS.BuyType= Int32.Parse(dr["BuyType"].ToString().Trim());

                            SS.FunctionState= Int32.Parse(dr["FunctionState"].ToString().Trim());

                            Add(SS);

                       }

 

                       dataSet.Clear();

                       dataSet.Dispose();

 

                       return true;

                   }

              }

              catch (Exception ex)

              {

                   Error.Log("Town", ex.ToString());

                   dataAdapter.Dispose();

                   return false;

              }

              finally

              {

                   data.Close();

                   data.Dispose();//釋放Database

              }

         }

         #endregion

 

     }

}

 

一點說明:

數據層類分類的代碼分了六塊:私有成員、構造函數、公共屬性、索引、私有方法、公有方法。這裏爲類建立了索引,這是集合類的必須元素。然後有一個私有方法,作用是把對象加到集合中,公有方法就是一個查詢方法,上面的例子中是通過參數傳的,其實也可以用屬性傳。這裏作了個約定,如果傳進的值爲-1便認爲此變量不起作用,基本跟存儲過程中的思想是一樣的。這個例子中的ScoreSetting對象是另外一個獨立的類,如下:

using System;

using System.Data;

using System.Data.SqlClient;

using Town.Data;

using Town.Log;

using System.Collections;

namespace Town.Com

{

     /// <summary>

     /// 功能:積分類

     /// 作者:Rexsp

     /// 創建日期:2004-01-14

     /// 修改者:

     /// 修改日期:

     /// </summary>

     public class ScoreSetting

     {

        

         #region 私有成員

         /// <summary>

         /// 分值設置ID

         /// </summary>

         private int id=-1;

         /// <summary>

         /// 功能ID

         /// </summary>

         private int functionID=-1;

          /// <summary>

         /// 操作ID

         /// </summary>

         private int operationID=-1;

         /// <summary>

         /// 角色類型ID

         /// </summary>

         private int roleTypeID=-1;

         /// <summary>

         /// 版塊類型ID

         /// </summary>

         private int bBSTypeID=-1;

         /// <summary>

         /// 積分

         /// </summary>

         private int score=-2000000000;

         /// <summary>

         /// 幣幣

         /// </summary>

         private int bB=-2000000000;

         /// <summary>

         /// 購買類型

         /// </summary>

         private int buyType=-1;

         /// <summary>

         /// 功能狀態

         /// </summary>

         private int functionState=-1;

         /// <summary>

         /// 是否更新分值

         /// </summary>

         #endregion

 

         #region 公有屬性

 

         /// <summary>

         /// 積分設置DI

         /// </summary>

         public int ID

         {

              get{return id;}

              set{id=value;}

         }

         /// <summary>

         /// 功能ID

         /// </summary>

         public int FunctionID

         {

              get{return functionID;}

              set{functionID=value;}

         }

         /// <summary>

         /// 操作ID

         /// </summary>

         public int OperationID

         {

              get{return operationID;}

              set{operationID=value;}

         }

         /// <summary>

         /// 角色類型

         /// </summary>

         public int RoleTypeID

         {

              get{return roleTypeID;}

              set{roleTypeID=value;}

         }

         /// <summary>

         /// 版塊類型

         /// </summary>

         public int BBSTypeID

         {

              get{return bBSTypeID;}

              set{bBSTypeID=value;}

         }

         /// <summary>

         /// 積分

         /// </summary>

         public int Score

         {

              get{return score;}

              set{score=value;}

         }

         /// <summary>

         /// 幣幣

         /// </summary>

         public int BB

         {

              get{return bB;}

              set{bB=value;}

         }

         /// <summary>

         /// 購買類型 0- 不是購買類型  1 - 一次性購買 2-反覆購買

         /// </summary>

         public int BuyType

         {

              get{return buyType;}

              set{buyType=value;}

         }

         /// <summary>

         /// 購買狀態:0-無此功能 1-有此功能 2-需要購買

         /// </summary>

         public int FunctionState

         {

              get{return functionState;}

              set{functionState=value;}

         }

         #endregion

         #region 構造函數

         public ScoreSetting()

         {

         }

         /// <summary>

         /// 重載構造函數

         /// </summary>

         /// <param name="id">積分設置ID</param>

         public ScoreSetting(int id)

         {

              this.id=id;

         }

         #endregion

 

         #region 公共方法

         /// <summary>

         /// ID獲得積分設置信息

         /// </summary>

         /// <returns>成功true,失敗false</returns>

         public bool GetInfoByID()

         {

           //代碼略

          }

 

         /// <summary>

         /// 添加積分設置

         /// </summary>

         /// <returns>成功true,失敗false</returns>

         public bool Add()

         {

              //代碼略

         }

         /// <summary>

         /// 編程積分設置

         /// </summary>

         /// <returns>成功返回true,失敗返回false</returns> 

         public bool Edit()

         {

              //代碼略

         }

         /// <summary>

         /// 刪除積分設置

         /// </summary>

         /// <returns>成功返回true,失敗返回false</returns>

         public bool Remove()

         {

              //代碼略

     }

}

 

一點說明:這個類包含四部分,私有成員、構造函數、公共屬性、公共方法,私有成員與數據庫表的字段是對應的,屬性與私有成員相對應。構造函數會初始數據表的key鍵,當然也可以重載構造函數初始另外的私有成員。這個類包含四個方法,也就是數據的四種操作:讀、寫、刪、改。

 

一、表示層(UI層)

這一層主要是讀取數據了。基本上會據需求填充到不同的服務器控件中。

 

              ScoreSettingCollection ssc = new ScoreSettingCollection();

              FunctionCollection funcc = new FunctionCollection();

              funcc.GetInfoByFunctionName("版名管理");

              int functionID=funcc[0].ID;

              ssc.GetSpecialInfo(functionID,0,roleTypeID,bBSTypeID,-1,-1,-1,-1);

              int sscCount=ssc.Count;

 

 

 

上面的這段代碼就是數據讀取過程,sscCount可以判斷有沒有得到數據。在得到數據的前提下填充控件之前,是把這一條條的數據重新循環組成一個DataTable然後再綁定數據。

 

  我暈,本來以爲一下子可以貼出來,不想還有限制,真麻煩,一篇文章貼子六次。嘿嘿!

  MSN:[email protected]  有問題可以一起探討

發佈了6 篇原創文章 · 獲贊 1 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章