下面的方法是我在实际开发中摸索出来的,可以在很大程度上简化调用存储过程的代码。

首先来看一下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
  )

 

C#执行存储过程的简化的更多相关文章

  1. Dapper完美兼容Oracle,执行存储过程,并返回结果集。

    Dapper完美兼容Oracle,执行存储过程,并返回结果集. 这个问题,困扰了我整整两天. 刚刚用到Dapper的时候,感觉非常牛掰.特别是配合.net 4.0新特性dynamic,让我生成泛型集合 ...

  2. JAVA使用JDBC技术操作SqlServer数据库执行存储过程

    Java使用JDBC技术操作SqlServer数据库执行存储过程: 1.新建SQLSERVER数据库:java_conn_test 2.新建表:tb_User 3.分别新建三个存储过程: 1>带 ...

  3. Oracle中执行存储过程call和exec区别

    Oracle中执行存储过程call和exec区别 在sqlplus中这两种方法都可以使用: exec pro_name(参数1..); call pro_name(参数1..); 区别: 1. 但是e ...

  4. C#获取执行存储过程的" 返回值"代码

    以下是C#代码: /// <summary> /// 执行存储过程,返回" 返回值" /// </summary> /// <param name=& ...

  5. MyCat 学习笔记 第十三篇.数据分片 之 通过HINT执行存储过程

    1 环境说明 VM 模拟3台MYSQL 5.6 服务器 VM1 192.168.31.187:3307 VM2 192.168.31.212:3307 VM3 192.168.31.150:  330 ...

  6. 原生jdbc执行存储过程

    //定时任务,结转 . //表名 fys_sch_lvyou2 ,存储过程名:fys_sch_lvyou2_carrayover //无参调用:{call insertLine} //有参调用:{ca ...

  7. 0327定时执行--存储过程--dbms_job--dbms_scheduler.create_job

    --oracle job 定时执行 存储过程 --建一张测试表 create table Person( name ), sex ) ); / --创建测试的存储过程 create or replac ...

  8. EF中执行存储过程,获取output返回值

    EF不能直接支持执行存储过程,于是使用转化成执行SQL语句的形式,却怎么也获取不到output的值,折腾的好久,终于解决了,分享下曲折的经历: public int AddVote(int title ...

  9. Oracle创建存储过程、执行存储过程基本语法

    >>>>>>>>>>>>>>>>>>>>>>>>> ...

随机推荐

  1. 有shi以来最详细的正则表达式入门教程

    本篇文章文字内容较多,但是要学习正则就必须耐心读下去,正则表达式是正则表达式其实并没有想像中的那么困难,但是想要熟练的掌握它,还是需要下功夫勤加练习的.这里讲一些正则表达式的语法和学习方法,大家还要多 ...

  2. jQuery基础之选择器

    摘自:http://www.cnblogs.com/webmoon/p/3169360.html jQuery基础之选择器 选择器是jQuery的根基,在jQuery中,对事件处理.遍历DOM和Aja ...

  3. [Unity3D入门]入门级游戏项目"坦克狙击手"更新

    [Unity3D入门]入门级游戏项目"坦克狙击手"更新 在上一篇中我分享了一个尚未完全写好的入门级unity3d项目"坦克狙击手". 本文介绍最新版的" ...

  4. Xamarin 技术全解析

    Xamarin 是一套基于C#语言的跨平台移动应用开发工具,今年2月份微软宣布收购Xamarin,而后在4月份进行的Build大会上微软宣布将会在各个版本的Visual Studio中免费提供Xama ...

  5. UWP入门教程1——UWP的前世今生

    目录 引言 设备族群 UI 和通用输入模式 通用控件和布局面板 工具 自适应扩展 通用输入处理 引言 在本篇文章中,可以掌握以下知识: 设备族群,如何决定目标设备 新的UI控件和新面板帮助你适应不同的 ...

  6. 知方可补不足~SQL2008中的发布与订阅模式

    回到目录 作用:完成数据库与数据库的数据同步 原理:源数据库发布需要同时的表,存储过程,或者函数:目标数据库去订阅它,当源发生变化时,目标数据库自己同步,注意,由于这个过程是SQL自动完成的,所以要求 ...

  7. PHP实现RESTful风格的API实例(三)

    接前一篇PHP实现RESTful风格的API实例(二) .htaccess :重写URL,使URL以 /restful/class/1 形式访问文件 Options +FollowSymlinks R ...

  8. 常用Math 方法

    /** * * @authors Your Name (you@example.org) * @date 2016-11-18 11:26:44 * @version $Id$ */ Math.pow ...

  9. loadrunner协议选择

    协议选择参考: 应用类型 协议选择 web网站 http/HTML FTP服务器 FTP 邮件服务器 IMAP\POP3\SMTP CS:客户端以ADO,OLEDB方法连接后台数据库 MS SQLSe ...

  10. WebClient.DownloadFile(线程机制,异步下载文件)

    线程机制(避免卡屏),异步下载文件. 我做网站的监控,WebClient.DownloadFile这个方法是我经常用到的,必要的时候肯定是要从网上下载些什么(WebRequest 也可以下载网络文件, ...