存储过程简介
简单的说,存储过程是由一些SQL语句和控制语句组成的被封装起来的过程,它驻留在数据库中,可以被客户应用程序调用,也可以从另一个过程或触发器调用。它的参数可以被传递和返回。与应用程序中的函数过程类似,存储过程可以通过名字来调用,而且它们同样有输入参数和输出参数。
根据返回值类型的不同,我们可以将存储过程分为三类:返回记录集的存储过程, 返回数值的存储过程(也可以称为标量存储过程),以及行为存储过程。顾名思义,返回记录集的存储过程的执行结果是一个记录集,典型的例子是从数据库中检索出符合某一个或几个条件的记录;返回数值的存储过程执行完以后返回一个值,例如在数据库中执行一个有返回值的函数或命令;最后,行为存储过程仅仅是用来实现数据库的某个功能,而没有返回值,例如在数据库中的更新和删除操作。

使用存储过程的好处
相对于直接使用SQL语句,在应用程序中直接调用存储过程有以下好处:
(1)减少网络通信量。调用一个行数不多的存储过程与直接调用SQL语句的网络通信量可能不会有很大的差别,可是如果存储过程包含上百行SQL语句,那么其性能绝对比一条一条的调用SQL语句要高得多。
(2)执行速度更快。有两个原因:首先,在存储过程创建的时候,数据库已经对其进行了一次解析和优化。其次,存储过程一旦执行,在内存中就会保留一份这个存储过程,这样下次再执行同样的存储过程时,可以从内存中直接调用。
(3)更强的适应性:由于存储过程对数据库的访问是通过存储过程来进行的,因此数据库开发人员可以在不改动存储过程接口的情况下对数据库进行任何改动,而这些改动不会对应用程序造成影响。
(4) 布式工作:应用程序和数据库的编码工作可以分别独立进行,而不会相互压制。
由以上的分析可以看到,在应用程序中使用存储过程是很有必要的。

两种不同的存储过程调用方法
为了突出新方法的优点,首先介绍一下在.NET中调用存储过程的“官方”方法。另外,本文的所有示例程序均工作于SqlServer数据库上,其它情况类似,以后不再一一说明。本文所有例子均采用C#语言。
要在应用程序中访问数据库,一般性的步骤是:首先声明一个数据库连接SqlConnection,然后声明一个数据库命令SqlCommand,用来执行SQL语句和存储过程。有了这两个对象后,就可以根据自己的需要采用不同的执行方式达到目的。需要补充的是,不要忘记在页面上添加如下的引用语句:using System.Data.SqlClient。
就执行存储过程来说,如果执行的是第一类存储过程,那么就要用一个DataAdapter将结果填充到一个DataSet中,然后就可以使用数据网格控件将结果呈现在页面上了;如果执行的是第二和第三种存储过程,则不需要此过程,只需要根据特定的返回判定操作是否成功完成即可。
(1)执行一个没有参数的存储过程的代码如下:

复制代码 代码如下:

SqlConnection conn=new SqlConnection(“connectionString”);
SqlDataAdapter da = new SqlDataAdapter();
da.SelectCommand = new SqlCommand();
da.SelectCommand.Connection = conn;
da.SelectCommand.CommandText = "NameOfProcedure";
da.SelectCommand.CommandType = CommandType.StoredProcedure;

然后只要选择适当的方式执行此处过程,用于不同的目的即可。
(2)执行一个有参数的存储过程的代码如下(我们可以将调用存储过程的函数声明为ExeProcedure(string inputdate)):

复制代码 代码如下:

SqlConnection conn=new SqlConnection(“connectionString”);
SqlDataAdapter da = new SqlDataAdapter();
da.SelectCommand = new SqlCommand();
da.SelectCommand.Connection = conn;
da.SelectCommand.CommandText = "NameOfProcedure";
da.SelectCommand.CommandType = CommandType.StoredProcedure;

(以上代码相同,以下为要添加的代码)

复制代码 代码如下:

param = new SqlParameter("@ParameterName", SqlDbType.DateTime);
param.Direction = ParameterDirection.Input;
param.Value = Convert.ToDateTime(inputdate);
da.SelectCommand.Parameters.Add(param);

这样就添加了一个输入参数。若需要添加输出参数:

复制代码 代码如下:

//设置存储过程的参数值,其中@ParameterName为存储过程的参数.
param = new SqlParameter("@ParameterName", SqlDbType.DateTime);
param.Direction = ParameterDirection.Output;
param.Value = Convert.ToDateTime(inputdate); //存储过程参数值;
da.SelectCommand.Parameters.Add(param);

若要获得参储过程的返回值:

复制代码 代码如下:

param = new SqlParameter("@ParameterName", SqlDbType.DateTime);
param.Direction = ParameterDirection.ReturnValue;
param.Value = Convert.ToDateTime(inputdate);
da.SelectCommand.Parameters.Add(param);
执行: DataSet myds=new DataSet();
da.Fill(myds,"tableName");

从上面的代码我们可以看出,当存储过程比较多或者存储过程的参数比较多时,这种方法会大大影响开发的速度;另外一方面,如果项目比较大,那么这些用于数据库逻辑的函数在以后的维护中也是一个很大的负担。那么,有没有一种改进的方法可以解决这个问题呢?想到在执行没有参数的存储过程时只需要传入一个存储过程的名字就可以调用相应的存储过程,而且在SqlServer数据库中我们可以直接在查询分析器中敲入“存储过程名(参数列表)”样的字符串就可以执行存储过程,那么,是否可以把这种思想应用到应用程序中呢?
于是在编译器中键入相应代码。这些代码是在调用不带参数的存储过程的代码的基础上改的。具体代码如下:

复制代码 代码如下:

SqlConnection conn=new SqlConnection(“connectionString”);
SqlDataAdapter da = new SqlDataAdapter();
da.SelectCommand = new SqlCommand();
da.SelectCommand.Connection = conn;
da.SelectCommand.CommandText = "NameOfProcedure('para1','para2',para3)";
da.SelectCommand.CommandType = CommandType.StoredProcedure;

为了使代码更具有代表性,要调用的存储过程的第一个和第二个参数都为字符串类型,第三个参数为整型。执行以后发现,完全可以达到预期的效果!

两种调用方法的比较
通过比较我们可以看到,第二种方法具有一个很明显的优点,那就是可以提高开发速度,节省开发时间,而且代码容易维护,在一定程度上也减少了系统大小。但是,由于对存储过程参数的处理比较笼统,如果要获取输出参数或者得到存储过程的返回值,这种方法就不能满足需要了。虽然如此,但是,这种方法毕竟可以让开发人员少些很大一部分的代码。如果不需要获取输出参数和返回值,那么几乎可以做到“一劳永逸”。因此在实际的程序开发中,这种方法还是具有一定的实用价值的。
用来创建DataRead的存储过程调用;

复制代码 代码如下:

//数据库连接字符串
string connStr="Server=localhost;database=stuIMS;uid=sa;pwd=admin";
//建立连接
SqlConnection conn=new SqlConnection(connStr);
//建立查询命令
SqlCommand myCommand=new SqlCommand("存储过程名",conn);
//调用存储过程名
myCommand.CommandType=CommandType.StoredProcedure;
//设置存储过程的参数值,其中@id 为存储过程的参数.
SqlParameter id=myCommand.Parameters.Add("@id",SqlDbType.NText);
id.Value=存储过程参数值;
//执行命令
SqlDataReader reader=myCommand.ExecuteReader();//读取数据
//或者
SqlDataReader reader=myCommand.ExecuteNonQuery();//数据更新 

c#中两种不同的存储过程调用与比较的更多相关文章

  1. jsp中两种include的区别【转】

    引用文章:http://www.ibm.com/developerworks/cn/java/j-jsp04293/ http://www.cnblogs.com/lazycoding/archive ...

  2. OC中两种单例实现方式

    OC中两种单例实现方式 写在前面 前两天探索了一下C++ 的单例,领悟深刻了许多.今天来看看OC中的单例又是怎么回事.查看相关资料,发现在OC中一般有两种实现单例的方式,一种方式是跟C++ 中类似的常 ...

  3. mybatis中两种取值方式?谈谈Spring框架理解?

    1.mybatis中两种取值方式? 回答:Mybatis中取值方式有几种?各自区别是什么? Mybatis取值方式就是说在Mapper文件中获取service传过来的值的方法,总共有两种方式,通过 $ ...

  4. JAVA 中两种判断输入的是否是数字的方法__正则化_

    JAVA 中两种判断输入的是否是数字的方法 package t0806; import java.io.*; import java.util.regex.*; public class zhengz ...

  5. 关于js中两种定时器的设置及清除(转载)

    1.JS中的定时器有两种: window.setTimeout([function],[interval]) 设置一个定时器,并且设定了一个等待的时间[interval],当到达时间后,执行对应的方法 ...

  6. JavaScript中两种类型的全局对象/函数【转】

    Snandy Stop, thinking is the essence of progress. JavaScript中两种类型的全局对象/函数 这里所说的JavaScript指浏览器环境中的包括宿 ...

  7. SQL Server两种分页的存储过程介绍

          由于现在很多的企业招聘的笔试都会让来招聘的写一个分页的存储过程,有的企业甚至要求应聘者用两种方式实现分页,如果没有在实际项目中使用过分页,那么很多的应聘者都会出现一定的问题,下面介绍两种分 ...

  8. Java中两种实现多线程方式的对比分析

    本文转载自:http://www.linuxidc.com/Linux/2013-12/93690.htm#0-tsina-1-14812-397232819ff9a47a7b7e80a40613cf ...

  9. mockito中两种部分mock的实现,spy、callRealMethod

    什么是类的部分mock(partial mock)?A:部分mock是说一个类的方法有些是实际调用,有些是使用mockito的stubbing(桩实现). 为什么需要部分mock? A:当需要测试一个 ...

随机推荐

  1. iOS自动处理键盘事件的第三方库:IQKeyboardManager

    我们写界面要考虑很多用户体验问题,键盘事件的响应就是比较麻烦的一种.我们需要监听键盘事件,考虑点击背景收起键盘.考虑键盘遮挡输入框问题等等,而且每个界面都要做这么一套.这个库帮我们解决了这个事情. 这 ...

  2. 【项目】iOS - 使用UIWebView占用内存过大

    通过其他博主介绍的解决这个问题的博客: http://blog.techno-barje.fr//post/2010/10/04/UIWebView-secrets-part1-memory-leak ...

  3. iOS - 如何自动播放H5中的音频

    场景:iOS端设备,App页面跳转到H5产品介绍,背景音乐无法播放.(为什么不能自动播放,因该是iPhone人性化设定吧~) 加载H5用UIWebView空间: 代码: CGRect rect = s ...

  4. BZOJ1915: [Usaco2010 Open]奶牛的跳格子游戏

    权限题,没有传送门. 这很显然是一道DP题,刚看完题目可能会比较懵逼.这道题如果不要求回去,那么就是一道很裸的DP题.但是本题要求回去而且回去的格子的前一个格必须是之前经过的. 先不考虑回去的路程,对 ...

  5. 如何使用alt键+数字键盘上的数字键打出特殊符号

    如何使用alt键+数字键盘上的数字键打出特殊符号 有时当我需要画示意图说明一个问题,但是苦于没有合适的符号,因此,这篇博文将简单介绍一些特殊的符号方便自己以及大家使用. 实现原理很简单:所有的字符(包 ...

  6. 关于Thread.Sleep(0)

    看到的文章,写的不错. 我们可能经常会用到 Thread.Sleep 函数来使线程挂起一段时间.那么你有没有正确的理解这个函数的用法呢?思考下面这两个问题:假设现在是 2008-4-7 12:00:0 ...

  7. idea community 配置已有的scala工程

  8. JavaWeb学习笔记——开发动态WEB资源(四)打印当前使用的是get方法

    该工程的名称是testhttp,功能是在页面中表格打印浏览过程中的相关头信息. 新建一个工程,然后在这个工程里面新建一个servlet,这样便可以省去编写web.xml的过程 以下是TestHttpS ...

  9. ecshop 获取某个商品的 所有订单信息 或者销量

    把一下代码放到 lib_main.php 1.统计某个下单商品的人数 function get_goods_ordernum($goods_id){ $sql = "select count ...

  10. IE6完美解决fix问题

    解决代码: _position: absolute; _top: expression(documentElement.scrollTop + + "px"); 完整代码: kef ...