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

首先来看一下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. 译文---C#堆VS栈(Part Three)

    前言 在本系列的第一篇文章<C#堆栈对比(Part Two)>中,介绍了值类型和引用类型在参数传递时的不同,本文将讨论如何应用ICloneable接口实现去修复引在堆上的用变量所带来的问题 ...

  2. C#Light V0.08A 执行字符串中的C#

    C#Lite第一批规划的功能已经全部完成 V0.08A 加入了var 表达式支持 完成了类型静态函数和静态成员的访问 之前已完成了非静态的 之所以还不进入beta是临时决定第一批就加入数组的功能. 项 ...

  3. django开发个人简易Blog——构建项目结构

    开发之前第一步,就是构造整个的项目结构.这就好比作一幅画,第一步就是描绘轮廓,有了轮廓,剩下的就是慢慢的填充细节.项目结构规划如下图: 项目结构描述: 本项目以fengzhengBlog为根目录. a ...

  4. [Unity3D]做个小Demo学习Input.touches

    [Unity3D]做个小Demo学习Input.touches 学不如做,下面用一个简单的Demo展示的Input.touches各项字段,有图有真相. 本项目已发布到Github,地址在(https ...

  5. git 修改管理

    查看修改: 撤销某一文件的修改(还没提交): 撤销所有文件的修改: git checkout .

  6. java API:AtomicInteger

    An int value that may be updated atomically. See the java.util.concurrent.atomic package specificati ...

  7. js实现『加载更多』功能实例

    DEMO : 滚动加载示例 关于如何实现『加载更多』功能,网上有插件可用,例如比较著名的使用iscroll.js实现的上拉加载更多.下拉刷新功能. 但实际用起来却是很麻烦.由于是第三方插件,要按照对方 ...

  8. MyBatis学习总结(七)——Mybatis缓存

    一.MyBatis缓存介绍 正如大多数持久层框架一样,MyBatis 同样提供了一级缓存和二级缓存的支持 一级缓存: 基于PerpetualCache 的 HashMap本地缓存,其存储作用域为 Se ...

  9. PHP两种redirect

    PHP两种redirect redirect header('Location: /admin_data.php'); exit(); redirect `echo "<script& ...

  10. Enerprise Solution Main 启动方法源代码

    .NET 系统以Main方法作为应用程序的启动入口点,Enterprise Solution的启动程序源代码如下: [STAThread] static void Main() { string MA ...