声明:该文已发表在《计算机应用》第23卷第11期上
摘要:在各种系统开发中,使用存储过程是一个良好的习惯,不仅可以带来临时表、函数、游标等特性,而且调试、升级、维护都变得方便。可是,几乎所有的存储过程的调用都是一种模式,主要差别也就是每个存储过程的参数不同。那么,可不可以采用一种方法来统一所有的存储过程调用,减少不必要的编程呢?在研究了SQL Server数据库及ASP.NET的基础上,我们实现了统一调用的方法,该方法只需要提供要调用的存储过程名,以及调用时提供具体的参数值就可实现任何存储过程的调用。
关键字:存储过程、系统表、信息结构视图、ADO.NET 文献标识码:②实用性技术成果报告(科技)、理论学习与社会实践总结(社科)
Call stored procedures in a same way in .NET
Abstract: Using stored procedures is a good habit in developing projects. It provides temporary table, functions and cursors, and debugging, upgrading, maintainence can benefit from it too. However, almost all calling to a stored procedure is a same pattern, the main difference between them is the parameters of every stored procedure. Then, can we call stored procedure in a same way in spite of their differences and reduce the programming code. We did it after studying SQL Server and .NET. Only information you provide is the stored procedure name and the values of its parameters, you needn’t to create the parameters yourself. Key word: Stord Procedure, System table, Information Schema, ADO.NET
摘要:在一个项目的开发中,经常会调用数据库中的存储过程。可是,几乎所有存储过程的调用都是同一个模式,主要区别就在于创建的每个参数类型、值等不一样。那么,能不能实现通过一个函数(或者类)调用所有的存储过程呢?本文在利用数据库提供的系统表原理上,实现了统一调用的方法,该方法只需要提供要调用的存储过程名,以及调用时提供具体的参数值就可实现任何存储过程的调用。
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.
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);
}
}
3.2返回结果数据集、返回值、传出参数集
创建好存储过程的参数之后,我们就可以调用这个存储过程了。由于在.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类型都可以采用这种方式创建。这样这个类就可以很通用,在任何项目中都可以发挥作用。
参考文献
[1] Ray Rankins, Paul Jensen, Paul Bertucci,SQL Server 2000实用全书,北京:电子工业出版社,2002
[2] MSDN Library January 2003, Microsoft Corporation.
作者简介:刘志波(1979-),男,湖南新化人,硕士,主要研究方向:神经网络与模式识别,办公自动化信息系统
email:[email protected]