惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

H
Help Net Security
博客园 - Franky
GbyAI
GbyAI
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
爱范儿
爱范儿
IT之家
IT之家
酷 壳 – CoolShell
酷 壳 – CoolShell
aimingoo的专栏
aimingoo的专栏
博客园_首页
MongoDB | Blog
MongoDB | Blog
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Recent Announcements
Recent Announcements
Scott Helme
Scott Helme
有赞技术团队
有赞技术团队
M
MIT News - Artificial intelligence
C
CERT Recently Published Vulnerability Notes
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
Jina AI
Jina AI
F
Fortinet All Blogs
N
Netflix TechBlog - Medium
L
LangChain Blog
L
LINUX DO - 最新话题
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
H
Hacker News: Front Page
MyScale Blog
MyScale Blog
P
Palo Alto Networks Blog
G
Google Developers Blog
Google DeepMind News
Google DeepMind News
AI
AI
T
Troy Hunt's Blog
Microsoft Azure Blog
Microsoft Azure Blog
阮一峰的网络日志
阮一峰的网络日志
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Vercel News
Vercel News
Microsoft Security Blog
Microsoft Security Blog
罗磊的独立博客
S
Secure Thoughts
大猫的无限游戏
大猫的无限游戏
博客园 - 叶小钗
人人都是产品经理
人人都是产品经理
Blog — PlanetScale
Blog — PlanetScale
博客园 - 司徒正美
Apple Machine Learning Research
Apple Machine Learning Research
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
博客园 - 三生石上(FineUI控件)
S
Security @ Cisco Blogs
Cloudbric
Cloudbric
E
Exploit-DB.com RSS Feed
Attack and Defense Labs
Attack and Defense Labs

博客园 - 阿风的博客

高压力下正则表达式的性能瓶颈 SQL SERVER2008不在同一局域网内实现订阅发布的方法 得到一个字符串的占位长度的函数 一个类似SPY++雷达手的工具 RPM V2.2发布 关于Table Schema 一段取得数据库中所有表字段及字段中文描述的SQL语句 多主键情况下的真分页存储过程 POP气球机v1.3 PCPOP多功能外挂v1.1 PCPOP多功能外挂v1.0 POP气球机 关于系统的垃圾文件 关于在同个页面实现多种编码的显示方法 关于几个比较经典的SQL语句 关于容器中的控件的使用 关于文件的上传。 网站开发步骤 网页源代码的获取方法
c#对调用存储过程的简化
阿风的博客 · 2005-10-31 · via 博客园 - 阿风的博客

在开发一个大型的项目的时候,数据库在多表,表关联复杂的情况下,使用存储过程是一种理想的选择,存储过程可以帮助我们处理一些数据

层逻辑比较复杂的事务。存储过程在首次运行时将被编译,因此在多次调用的时候会大大节省数据库服务器的负担,提高程序的运行效率。

但是在.net里调用存储过程的方法是比较痛苦的,特别是在多个传入传出的情况下。
如下面的一个存储过程:

CREATE PROCEDURE MEMBER_TEACHER_GET
@pid as int=null,  --教师代号
@depart as int=null,  --教师部门
@uname as nvarchar(18)='',  --登陆名
@tname as nvarchar(20)='',   --真实姓名
@status as char(10)='',      --状态
@count  as tinyint=null     --真分页时所用
 AS

--处理过程省略

GO

在传统上调用存储过程的方法如下:

            string conn_str=this.txtConn.Text.Trim();
            SqlConnection myconn
=new SqlConnection(conn_str);
            SqlCommand mycomm
=new SqlCommand("MEMBER_TEACHER_GET",myconn);
            mycomm.CommandType
=CommandType.StoredProcedure;

            SqlParameter myp1
=new SqlParameter("@pid",SqlDbType.Int,4);
            mycomm.Parameters.Add(myp1);
            mycomm.Parameters[
"@pid"].Value="1001";

            SqlParameter myp2
=new SqlParameter("@depart",SqlDbType.Int,4);
            mycomm.Parameters.Add(myp2);
            mycomm.Parameters[
"@depart"].Value="1000";

            SqlParameter myp3
=new SqlParameter("@uname",SqlDbType.NVarChar,18);
            mycomm.Parameters.Add(myp3);
            mycomm.Parameters[
"@uname"].Value="t1";

            SqlParameter myp4
=new SqlParameter("@tname",SqlDbType.NVarChar,20);
            mycomm.Parameters.Add(myp4);
            mycomm.Parameters[
"@tname"].Value="教师1";

            SqlParameter myp5
=new SqlParameter("@status",SqlDbType.TinyInt,1);
            mycomm.Parameters.Add(myp5);
            mycomm.Parameters[
"@status"].Value="1";


            SqlDataAdapter myAdapter
=new SqlDataAdapter();
            myAdapter.SelectCommand
=mycomm;

            DataTable d
=new DataTable();
            myAdapter.Fill(d);
            myAdapter.Dispose();

            
this.dataGrid1.DataSource=d;

其中大部分的时间都放在对参数的传入上了。调用一个存储过程尚是如此,在一个大一点的项目里存储过程几百的个情况下,这样就会给程序

开发带来很大的重复劳动和繁琐的工作量。

而实际上,我们完全可以把这种繁琐的事情封装起来,这是封装后的所调用存储过程的全部代码:

conn c=new conn(this.txtConn.Text.Trim());
DataTable dt
=c.getDataProcedure("MEMBER_TEACHER_GET",new object[] {1001,1000,"t1","教师1",1});
this.dataGrid1.DataSource=dt;


最重只需要传入存储过程的名称和对应的参数即可。
下面分析conn类中getDataProcedure方法的实现。

在传统对存储过程参数的参入下是让存储过程里的参数名和传入参数值一一对应。而实际上,在数据库里,存储过程中的传入参数都是事先写

好,定死的,因此,我们完全可以省去这部分代码的输入,写一个方法getProcParameters让它去数据库里去取得,返回一个ArrayList列表。

        public ArrayList getProcParameters(string proc)
        
{
            System.Data.SqlClient.SqlCommand mycomm
=new SqlCommand("sp_sproc_columns",myconn);
            DataTable td
=new DataTable();
            mycomm.CommandType
=CommandType.StoredProcedure;

            mycomm.Parameters.Add(
"@procedure_name",(object)proc);
            System.Data.SqlClient.SqlDataAdapter myadapter
=new SqlDataAdapter(mycomm);
            myadapter.Fill(td);
            myadapter.Dispose();

            ArrayList al
=new ArrayList();
            
for(int i=1;i<td.Rows.Count;i++)
            
{
                al.Add(td.Rows[i][
3].ToString());
            }

            
            
return al;
        }

这样,我们就可以在getDataProcedure里我们就可以自动将存储过程的参数和外面传入的参数值一一对应起来。问题就解决了。

        public DataTable getDataProcedure(string proc,object[] parms)
        
{
            System.Data.SqlClient.SqlCommand mycomm
=new SqlCommand(proc,myconn);
            mycomm.CommandType
=CommandType.StoredProcedure;

            ArrayList al
=getProcParameters(proc);

            
for(int i=0;i<parms.Length;i++)
            
{
                mycomm.Parameters.Add(al[i].ToString(),parms[i]);
            }


            SqlDataAdapter myAdapter
=new SqlDataAdapter();
            myAdapter.SelectCommand
=mycomm;

            DataTable d
=new DataTable();
            myAdapter.Fill(d);
            myAdapter.Dispose();

            
return d;
        }


当然,为了提高程序的效率,我们可以改写方法getProcParameters,可以从一个XML里读取存储过程的参数,或者也可以先将所有的参数初始

化到一个数组里去。有兴趣的朋友可以一试。