程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> C#執行存儲過程的簡化

C#執行存儲過程的簡化

編輯:C#入門知識

下面的方法是我在實際開發中摸索出來的,可以在很大程度上簡化調用存儲過程的代碼。

首先來看一下C#調用存儲過程的一般過程:
1、打開數據庫連接SqlConnection;
2、生成一個SqlCommand;
3、向命令對象填充參數;
4、執行存儲過程;
5、關閉連接;
6、其他操作。

我這裡講的主要是簡化第3步操作,最終在調用存儲過程的時候只需要傳遞存儲過程的名字和相應的參數值。調用示例如下:
        dbAccess.run("p_am_deleteFile", new object[]{LoginId, Request.UserHostAddress, fileId});

由於在填充參數的時候必須要兩個值,一個是參數的名字,一個是參數的值。參數值是由外部傳入的,不用考慮;而參數名稱是和存儲過程相關的東西,應該可以由存儲過程名稱來確定而不用每次調用的時候寫上一遍。對於這個問題,如果能將存儲過程的參數保存到一個全局的地方,那麼在調用存儲過程的時候只要能根據存儲過程的名字去索引就可以了。具體實現的時候我是將這些信息保存在數據庫訪問組件裡面,采用名字/值對的方式。代碼如下:
public class InfoTable : NameObjectCollectionBase
{
   public object this[string key]  
   {
    get  
    {
     return(this.BaseGet(key));
    }
    set  
    {
     this.BaseSet(key, value);
    }
   }
}
protected static InfoTable procInfoTable = new InfoTable();
public static InfoTable ProcInfoTable
{
   get
   {
    return procInfoTable;
   }
}

這樣的話,在實際調用存儲過程的時候就只需要去查這張表就可以知道存儲過程的參數名了。實現代碼如下:
public DataTable run(string procName, object[] parms, ref int retValue)
{
 string[] paramInfo = (string[])(procInfoTable[procName]);
 if (paramInfo == null)
 {
  ErrorInfo.setErrorInfo("未取得" + procName + "的參數!");
  return null;
 }

 bool bOpened = (dbConn.State == ConnectionState.Open);
 if (!bOpened && !connect())
 {
  return null;
 }

 DataSet ds = new DataSet();    
 try
 {
  SqlCommand cmd = new SqlCommand(procName, dbConn);
  cmd.CommandType = CommandType.StoredProcedure;

  for (int i = 0; i < parms.Length && i < paramInfo.Length; ++i)
  {
   cmd.Parameters.Add(new SqlParameter(paramInfo[i], parms[i]));
  }

  SqlParameter parmsr = new SqlParameter("return", SqlDbType.Int);
  parmsr.Direction = ParameterDirection.ReturnValue;
  cmd.Parameters.Add(parmsr);

  SqlDataAdapter adp = new SqlDataAdapter(cmd);
  adp.Fill(ds);
  retValue = (int)(cmd.Parameters["return"].Value);
 }
 catch (Exception ex)
 {
  ErrorInfo.setErrorInfo(ex.Message);

  retValue = -1;
 }

 if (!bOpened)
  close();

 if (ds.Tables.Count > 0)
  return ds.Tables[0];
 else
  return null;
}

可以看出,每個存儲過程的參數列表存儲為了一個string[]。接下來的工作就是將系統裡頭許許多多的存儲過程的參數填充到表ProcInfoTable中。我所用的數據庫是Sql Server 2000,下面給出一個存儲過程來解決這個煩人的問題:
create PROCEDURE dbo.p_am_procInfo
(
 @procName t_str64 --存儲過程的名字
)
AS
begin
 set nocount on

 if @procName = '' begin
  select name as procName
  from sysobjects
  where substring(sysobjects.name, 1, 5) = 'p_am_'
 end
 else begin
  select 
   syscolumns.name as paramName
  from sysobjects, syscolumns
  where sysobjects.id = syscolumns.id
   and sysobjects.name = @procName
  order by colid
 end
 
end

這個存儲過程有兩個作用,在沒有傳遞存儲過程的名字的時候,該存儲過程返回所有以”p_am_”開頭的存儲過程的名字;在傳入了相應的存儲過程名字後,該存儲過程返回該存儲過程的參數列表。這樣一來,我們在程序開始的地方就可以將系統裡的存儲過程參數列表取出來並保存到數據庫訪問組件的ProcInfoTable屬性中了。具體代碼如下:
span.DBAccess dbAccess = new span.DBAccess();

//
//構造取存儲過程的參數表
//
span.DBAccess.ProcInfoTable["p_am_procInfo"] = new string[]{"@procName"};

//
//取得其他存儲過程列表
//
DataTable dt = dbAccess.run("p_am_procInfo", new object[]{""});
if (dt == null || dt.Rows.Count <= 0)
{
 return;
}

//
//取得其他存儲過程的參數表
//
foreach (DataRow dr in dt.Rows)
{
 DataTable dtParams = dbAccess.run("p_am_procInfo", new object[]{dr["procName"]});
 if (dtParams != null)
 {
  string[] paramInfo = new string[dtParams.Rows.Count];
  for (int i = 0; i < dtParams.Rows.Count; ++i)
   paramInfo[i] = dtParams.Rows[i]["paramName"].ToString();

  span.DBAccess.ProcInfoTable[dr["procName"].ToString()] = paramInfo;
 }
}

至此,全部技術細節介紹完畢。另外,數據庫訪問對象的幾個接口函數也一並給出:

//打開、關閉數據庫連接
public bool connect(string strConn)
public bool connect()
public bool close()

//執行SQL命令(只有一個int返回)
public int exec(string procName, object[] parms)
public int exec(string sql)

//運行(返回一個DataTable)
public DataTable run(string procName, object[] parms, ref int retValue)
public DataTable run(string procName, object[] parms)
public DataTable run(string sql)

//分頁查詢(頁號從1開始,返回一個DataTable)
public DataTable pageQuery
  (
   string selectCmd,
   int pageSize,
   int pageNumber
  )

 

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