摘要:在一个项目的开发中,经常会调用数据库中的存储过程。可是,几乎所有存储过程的调用都是同一个模式,主要区别就在于创建的每个参数类型、值等不一样。那么,能不能实现通过一个函数(或者类)调用所有的存储过程呢?本文在利用数据库提供的系统表原理上,实现了统一调用的方法,该方法只需要提供要调用的存储过程名,以及调用时提供具体的参数值就可实现任何存储过程的调用。

Abstract: We have to call stored procedures of database systems during a development of a project. However, calling a stored procedures are almost the same, the main difference is the difference between parameters’ type or value etc. Can we call any stored procedures through a function (or a class)? Based on the system tables provided by database systems, We wrote a class to call any stored procedures in this article. To call a stored procedure, the only parameters you provide are the name of the stored procedure and the value of all parameters of the stored procedure.
1.       引言
在各种系统开发中,使用存储过程是一个良好的习惯,不仅可以带来临时表、函数、游标等特性,而且调试、升级、维护都变得方便。在存储过程中能够把数据经过处理再返回,这样能够对数据提供更多的分析和控制。
在存储过程的调用中,我们发现存储过程的调用都几乎是如下的模式:
1.声明SqlConnection
2.声明SqlCommand,并且设置其Connection属性为刚声明的SqlConnection实例,设置CommandName为存储过程名,CommandType为存储过程。
3.往刚声明的SqlCommand实例的Parameters集合中添加所有的存储过程调用需要的参数
4.呼叫SqlCommand的ExecuteReader()方法来得到存储过程的返回行集
4.声明SqlDataAdapter和DataSet,设置SqlDataAdapter的SelectCommand属性为3中声明的实例,再调用其Fill方法来把返回的行集填充到DataSet中
5.关闭SqlConnection对象
6.释放声明的各对象实例
(说明:4指的是两种数据提取方法)
在这个调用过程中,我们发现几乎所有的存储过程调用都是这个模式,之间的区别就在第2步中的存储过程名不同和第3步中各个存储过程调用使用的参数是不一样的,他们有参数名字、方向、数据类型、长度等的区别。
那么,有没有一种方法可以实现所有的存储过程调用?即只需要提供存储过程名,然后把参数值传入调用方法即可实现存储过程的调用,再用某些数据结构来保存返回的行集、传出参数值、过程返回值。经过研究SQL Server的系统表,我们发现这个想法是切实可行的。
2.系统表与信息结构视图
SQL Server等关系型数据库都将元数据以某种方式保存在数据库中,在SQL Server中就是系统数据库和系统表。安装SQL Server后会自动生成四个系统数据库:master, model, msdb与tempdb。master数据库是SQL Server中所有系统级信息的仓库。登录帐号、配置设置、系统存储过程和其他数据库的存在性都记录在master数据库中。msdb数据库保存SQL Server Agent的信息。定义作业、操作员和警报时,他们存放在msdb中。model是个模框,用于所有用户生成的数据库。生成新数据库时,将model复制,建立所要的对象。tempdb保存SQL Server中的临时对象。显示生成的临时表和临时存储过程以及系统生成的临时对象都利用tempdb。[1]
而且每个数据库中都有自己的系统表。这些系统表被用来保存配置和对象信息。从这些系统表中,我们就可以得到每个存储过程的所有参数的信息。syscolumns表中就保存了这些信息。其中有参数名、类型、长度、方向等需要用到我们方法中的信息。
不过,系统表中的字段会随着SQL Server版本的变化而变化。比如syscolumns中的type和xtype就是这样的一个变化例子,他们都保存了类型的信息。要让我们的方法适应SQL Server的版本变化要求,就要用到信息结构视图。
ANSI-92将信息结构视图定义为一组提供系统数据的视图。通过利用该视图,可以将实际系统表从应用程序中隐藏起来。系统表的改变就不会影响到应用程序,这样应用程序就可以独立于数据库厂家和版本。[1]
ANSI-92和SQL Server支持用三段命名结构引用本地服务器上的对象。ANSI-92术语称为catalog.schema.object,而SQL Server称为database.owner.object。[1]比如我们要找到所有存储过程的所有参数信息,就可以用:
select * from INFORMATION_SCHEMA.PARAMETERS
如果要找到某个存储过程的所有参数信息,就是:
select * from INFORMATION_SCHEMA.PARAMETERS where SPECIFIC_NAME =’Proc1’
有了信息结构视图,我们的问题就解决了一大半了。下面我们看如何在.NET中实现我们的方法。
 
3.实现方法
实现的重点就放在如何根据存储过程名来得到它的所有的参数信息,再根据这些参数信息自动的创建各个参数。为了让这些动作自动化,声明SqlConnection、SqlCommand、SqlParameter的过程,创建各个SqlParameter的过程对用户来说都应该不可见。用户唯一需要提供的就是存储过程的名字,然后就是在调用的时候提供各个参数,甚至连他们的类型都不需要提供。
31获得和创建存储过程的参数
如何获得并且创建要调用的存储过程的参数是一个重点,通过信息结构视图我们可以自动的实现这个步骤。
// 获得和创建存储过程的参数
private void GetProcedureParameter(params object[] parameters)
{
        SqlCommand myCommand2 = new SqlCommand();
 
        myCommand2.Connection = this.myConnection;
        myCommand2.CommandText = "select * from INFORMATION_SCHEMA.PARAMETERS where SPECIFIC_NAME='" +this.ProcedureName+ "' order by ORDINAL_POSITION";
 
        SqlDataReader reader = null;
        reader = myCommand2.ExecuteReader();
 
                // 创建返回参数
                myParameter = new SqlParameter();
                myParameter.ParameterName = "@Value";
                myParameter.SqlDbType = SqlDbType.Int;
                myParameter.Direction = ParameterDirection.ReturnValue;
 
                myCommand.Parameters.Add(myParameter);
 
                int i = 0;
                // 创建各个参数,在这个地方可以自动的创建SqlParameter的类型,值,方向等属性
                while(reader.Read())
                {
                    myParameter = new SqlParameter();
 
                    myParameter.ParameterName = reader["PARAMETER_NAME"].ToString();
                    myParameter.Direction = reader["PARAMETER_MODE"].ToString()=="IN"?ParameterDirection.Input:ParameterDirection.Output;
 
                    switch(reader["DATA_TYPE"].ToString())
                    {
                            case "int" :
                                if(myParameter.Direction == ParameterDirection.Input)
                                        myParameter.Value = (int)parameters[i];
                                myParameter.SqlDbType = SqlDbType.Int;
            
                                break;
                           //...省略了很多具体的类型处理
                                default : break;
                    }
                    i++;
 
                    myCommand.Parameters.Add(myParameter);
                }
 
}
 
 
 
 
32返回结果数据集、返回值、传出参数集
创建好存储过程的参数之后,我们就可以调用这个存储过程了。由于在.NET中,常用的返回结果集的类为SqlDataReader和DataSet,而SqlDataReader必须在保持连接的状态下才可以使用,DataSet却不需要。在我们的实现中,连接应该在调用之后就断开,因此采用DataSet来保存返回结果集。
public SqlResult Call(params object[] parameters)
{
        // SqlResult是自己定义的用于保存结果数据集、返回值、传出参数集的类
        SqlResult result = new SqlResult();
 
        // 根据需要定义自己的连接字符串
        myConnection = new SqlConnection(ConnectionString);
 
        myCommand = new SqlCommand(this.ProcedureName, myConnection);
        myCommand.CommandType = CommandType.StoredProcedure;
 
        SqlDataAdapter myAdapter = new SqlDataAdapter(myCommand);
 
        myConnection.Open();
        // 获得和创建存储过程的参数,并且设置好值
        GetProcedureParameter(parameters);
 
        myAdapter.Fill(result.dataSet, "Table");
        
        // 获得存储过程的传出参数值和名字对,保存在一个Hashtable中
        GetOutputValue(result);
 
        // 在这里释放各种资源,断开连接
        myAdapter.Dispose();
        myCommand.Dispose();
        myConnection.Close();
        myConnection.Dispose();
 
 
        return result;
}
4.进一步工作
虽然我们在这里的实现是针对SQL Server数据库,但是对于任何提供了信息结构视图,符合ANSI-92标准,或者是提供了元数据的数据库都可以使用这种方法来实现。我们把它封装成一个SqlProcedure类,在需要的时候可以很简单的就调用了存储过程,减少了大量基本上是重复的代码工作。
为了让SqlProcedure类支持更过的数据类型,在GetProcedureParameter()方法中需要根据自己的需要来分析各个参数的类型、方向、长度、默认值等信息,然后来创建这个参数。基本上任何类型都是能够实现的,甚至连image类型都可以采用这种方式创建。这样这个类就可以很通用,在任何项目中都可以发挥作用。

转载于:https://www.cnblogs.com/ivanyb/archive/2008/02/16/1070968.html

.NET中统一的存储过程调用方法(收藏)相关推荐

  1. 在mybatis用mysql的代码块_关于Mybatis 中使用Mysql存储过程的方法

    1.存储过程的简介 我们常用的操作数据库语言SQL语句在执行的时候需要要先编译,然后执行,而存储过程(Stored Procedure)是一组为了完成特定功能的SQL语句集,经编译后存储在数据库中,用 ...

  2. [转载]:C#两种不同的存储过程调用方法

    两种不同的存储过程调用方法 为了突出新方法的优点,首先介绍一下在.NET中调用存储过程的"官方"方法.另外,本文的所有示例程序均工作于SqlServer数据库上,其它情况类似,以后 ...

  3. java中如何使用反射调用方法以及获得类中的属性

    使用反射获取类中的方法: 1):获取方法所在类的字节码对象. 2):获取方法. ------------------------------------------------------------ ...

  4. Struts2中Action的动态调用方法

    在Struts2中,Action执行的时候并不一定要执行execute,我们可以指定Action执行哪个方法,下面分别介绍三种方法来指定Action执行哪个方法: 1.第一种方法,通过Action里的 ...

  5. 利用.Net中的反射动态调用方法

    .Net中的反射功能是极其强大的,本篇先用他来动态调用方法 看如下一个类 Public Class A { public void InvokeMethod(string methodname) { ...

  6. js中闭包函数的调用方法

    function fn() {let num = 10 // 只能在函数里面使用,外面看不到---- 数据私有化console.log('外');return function g() {num++c ...

  7. mysql数据库存储过程及调用方法

    mysql数据库存储过程及调用方法 mysql5.0以后就支持存储过程了,目前mysql的6.0Alpha版也已经推出.6.0不仅支持大型数据库如oracle等的绝大部分功 能,如存储过程.视图.触发 ...

  8. Spring中利用applicationContext.xml文件实例化对象和调用方法

    Spring中实例化对象和调用方法入门 1.jar包和xml的准备 已上传至百度云盘,链接: https://pan.baidu.com/s/1CY0xQq3GLK06iX7tVLnp3Q 提取码: ...

  9. SQL Server中的部分存储过程

    介绍 (Introduction) SQL is an old language - almost 50 years! The first commercially-available version ...

最新文章

  1. 有关C/C++中,表达式计算顺序的问题,以及表达式内部变量“副作用”问题(转)...
  2. 工业4.0进行时:工业机器人为何能够快速爆发?
  3. 关于DataGridViewComboBoxColumn的二三事
  4. 超适合新手的Oracle查询语句
  5. python自带编译器如何生成exe_别再问我怎么Python打包成exe了!
  6. WEBTIMER控件研究的心得:丢开书本做一个WebTimer
  7. win linux 远程桌面连接,Windows 连接 Ubuntu 16.04 远程桌面
  8. 颠覆认知!完美赌徒,到底是如何用数学打造经济神话?!
  9. C 获得程序执行时间
  10. eas库存状态调整单不能反审核_把握 商品 周转,做好 动态 库存 管理
  11. 数据库原理(一)—— 关系代数
  12. 14.企业应用架构模式 --- Web表现模式
  13. UnityWebReqest和WWW,请求web数据打包到Android手机上,报错 Unknown error记录
  14. (二) GNU/GCC 编译器及其编译流程概述
  15. 金融资产收益率计算中百分比收益率和对数收益率有什么区别?
  16. 熊出没电锯机器人哪一集_熊出没伐木机器人第几集 熊出没光头强造伐木机器人是哪一集?...
  17. 国家税务总局全国增值税发票查验平台-客户端
  18. 三天打鱼两天晒网的直接差距
  19. hello.i 预处理文件
  20. 星形接法和三角形接法电压和电流关系

热门文章

  1. 大数据_Flink_流式处理_简介_认识一下什么是BI中的ETL---Flink工作笔记0005
  2. Netty工作笔记0071---Protobuf传输多种类型
  3. SpringCloud工作笔记73---Http协议操作工具集合
  4. ARCGIS地理信息系统学习笔记001--认识ARCGIS
  5. DOTNET零碎要点---1.vb.net利用Oracle.DataAccess.dll链接Oracle数据库
  6. cocos2d-x之 利用富文本控件解析xhml标签(文字标签,图片标签,换行标签,标签属性)...
  7. 半小时让你成为EXCEL高手
  8. Spring + Spring MVC + mybatis 下的 junit4 注入单元测试
  9. 无锡 计算机学校排名,无锡中职学校有哪些 前20排名
  10. 禅道测试套件怎么用_【分享】—如何学习软件测试