引言:
參與了一個大型社區程序的開發,現在將相關開發經驗陸續總結出來,和大家探討一下。本節主要想與大家探討一種數據讀取方案:集合類代替直接從數據庫中獲取的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 ---
一點說明:
此存儲過程會
一、 數據層類:
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>
///
/// </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;
上面的這段代碼就是數據讀取過程,
我暈,本來以爲一下子可以貼出來,不想還有限制,真麻煩,一篇文章貼子六次。嘿嘿!
MSN:[email protected] 有問題可以一起探討