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
)
C#执行存储过程的简化的更多相关文章
- Dapper完美兼容Oracle,执行存储过程,并返回结果集。
Dapper完美兼容Oracle,执行存储过程,并返回结果集. 这个问题,困扰了我整整两天. 刚刚用到Dapper的时候,感觉非常牛掰.特别是配合.net 4.0新特性dynamic,让我生成泛型集合 ...
- JAVA使用JDBC技术操作SqlServer数据库执行存储过程
Java使用JDBC技术操作SqlServer数据库执行存储过程: 1.新建SQLSERVER数据库:java_conn_test 2.新建表:tb_User 3.分别新建三个存储过程: 1>带 ...
- Oracle中执行存储过程call和exec区别
Oracle中执行存储过程call和exec区别 在sqlplus中这两种方法都可以使用: exec pro_name(参数1..); call pro_name(参数1..); 区别: 1. 但是e ...
- C#获取执行存储过程的" 返回值"代码
以下是C#代码: /// <summary> /// 执行存储过程,返回" 返回值" /// </summary> /// <param name=& ...
- 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 ...
- 原生jdbc执行存储过程
//定时任务,结转 . //表名 fys_sch_lvyou2 ,存储过程名:fys_sch_lvyou2_carrayover //无参调用:{call insertLine} //有参调用:{ca ...
- 0327定时执行--存储过程--dbms_job--dbms_scheduler.create_job
--oracle job 定时执行 存储过程 --建一张测试表 create table Person( name ), sex ) ); / --创建测试的存储过程 create or replac ...
- EF中执行存储过程,获取output返回值
EF不能直接支持执行存储过程,于是使用转化成执行SQL语句的形式,却怎么也获取不到output的值,折腾的好久,终于解决了,分享下曲折的经历: public int AddVote(int title ...
- Oracle创建存储过程、执行存储过程基本语法
>>>>>>>>>>>>>>>>>>>>>>>>> ...
随机推荐
- statcounter统计的浏览器市场占有率
Source: StatCounter Global Stats - Browser Market Share
- Identity自增序列/唯一断标识
ThreadStatic应用(Identity补完) 用于在高并发环境中的自增序列维护和快速创建唯一不重复的短标识,该类是线程安全的 如在ORM组件中,创建唯一的参数名 特点: 高并发环境下的性能保证 ...
- HttpContext.Current:异步模式下的疑似陷阱之源
最近园子里首页有好几篇文章都是讲异步编程的,尤其是几篇讲博客园自身的异步化建设的文章,看了以后很有收获. 闲暇之余再重新查查资料温故知新学习一遍,重新认识了SynchronizationContext ...
- Bootstrap~页面的布局
回到目录 Bootstrap作为支持响应式布局的一个前端插件,确实发挥着重要的作用,无论你是在手机,平板还是PC上浏览网页,都能达到不错的效果,这一切一切,都是bootstrap带给我们的! 今天主要 ...
- Atitit 颜色平均值cloor grb hsv模式的区别对比
Atitit 颜色平均值cloor grb hsv模式的区别对比 使用hsv模式平均后会变得更加的靓丽一些..2 public class imgT { public static void main ...
- iOS中app启动闪退的原因
这种情况应和所谓的内存不足关系不大,很少有程序会在初始化时载入大量内容导致崩溃,并且这类问题也很容易在开发阶段被发现,所以内存不足造成秒退的可能性低(内存不足退,通常是程序用了一段时间,切换了几个画面 ...
- Mybatis中SqlMapper配置的扩展与应用(3)
隔了两周,首先回顾一下,在Mybatis中的SqlMapper配置文件中引入的几个扩展机制: 1.引入SQL配置函数,简化配置.屏蔽DB底层差异性 2.引入自定义命名空间,允许自定义语句级元素.脚本级 ...
- 快速入门系列--WCF--05事务
最近开始WCF相关知识的学习,虽然实际工作中使用公司自己的一套SOA系统,但微软的一套服务架构还是具有很大的参考意义.除了WCF的一些基础使用,相对比较复杂的内容有分布式的事务和通信的安全等,不过基本 ...
- iOS越狱开发(一)
做越狱开发也有一些时间了,有很多东西想总结一下,希望给他人一些借鉴,也是自己对过去开发经历的一些总结.个人不推荐使用盗版,这里主要以技术介绍为主. 这个系列里面主要介绍怎样进行越狱开发,涉及到以下几个 ...
- RoundedImageView,实现圆形、圆角矩形的注意事项
RoundedImageView是gitHub上面的一个开源组件(https://github.com/vinc3m1/RoundedImageView),实现一些圆形或者圆角矩形是很方便的, < ...