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创建存储过程、执行存储过程基本语法
>>>>>>>>>>>>>>>>>>>>>>>>> ...
随机推荐
- ASP.NET一般处理程序访问Session问题
我们在使用一般处理程序的时候,访问Session会出现如下错误: 解决方案如下: //引用命名空间 using System.Web.SessionState; //继承IRequiresSessio ...
- hibernate继承(转)
http://justsee.iteye.com/blog/1070588 一.继承关系_整个继承树映射到一张表 对象模型(Java类结构) 一个类继承体系一张表(subclass)(表结构) Emp ...
- IOS UIView 04- 自定义控件
注:本人是翻译过来,并且加上本人的一点见解. 前言 本文将讨论一些自定义视图.控件的诀窍和技巧.我们先概述一下 UIKit 向我们提供的控件,并介绍一些渲染技巧.随后我们会深入到视图和其所有者之间的通 ...
- Java程序员的日常 —— 响应式导航Demo
这两天想要做响应式的页面,于是本着重复造轮子的想法,模仿Bootstrap官网,精简了一个响应式导航的Demo. 效果 代码 <!DOCTYPE html> <html> &l ...
- Atiit 如何手写词法解析器
Atiit 如何手写词法解析器 1.1. 通过编程直接从正则->nfa->dfa->表驱动词法解析一条龙自动生成.那是用程序自动生成是需要这样的,自己手写完全不必要这么复杂1 1.2 ...
- Atitit.java expression fsm 表达式词法分析引擎 v2 qaa.docx
Atitit.java expression fsm 表达式词法分析引擎 v2 qaa.docx C:\0workspace\AtiPlatf_cms\src\com\attilax\fsm\Java ...
- Ajax技术使用
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding= ...
- sql 循环处理表数据中当前行和上一行中某值相+/-
曾经,sql中循环处理当前行数据和上一行数据浪费了我不少时间,学会后才发现如此容易,其实学问就是如此,难者不会,会者不难. 以下事例,使用游标循环表#temptable中数据,然后让当前行和上一行中的 ...
- select元素javascript常用操作 转
/*------------------------------------------------------ *作者:xieyu @ 2007-08-14 *语言:JavaScript *说明:s ...
- javase基础复习攻略《九》
本篇将为大家总结JAVA中的线程机制,谈到线程,大家一定会问线程和进程有什么区别?刚接触进程时我也有这样的疑问,今天就为大家简单介绍一下进程和线程.进程(Process)是计算机中的程序关于某数据集合 ...