基于C#的WinForm开发中存储过程应用研究

2018-05-15 08:31于磊
软件导刊 2018年4期

于磊

摘 要:在基于C#的WinForm+SQL数据库应用开发中,存在着大量数据库操作,直接使用命令字符串进行操作的常规方式存在执行速度低、增加网络通信量、修改困难等问题。改善上述问题的有效方法是利用SQL Server提供的存储过程进行数据库操作。在实际开发中应用存儲过程,采用不同方法进行对比测试,结果表明,在开发中合理应用存储过程能有效地将应用与数据操作分离,提高运行效率,提高数据库访问的安全性并增加灵活性。

关键词:C#;WinForm;SQL;存储过程

DOI:10.11907/rjdk.172524

中图分类号:TP319

文献标识码:A 文章编号:1672-7800(2018)004-0178-02

Abstract:In C# based WinForm+SQL application development, there is a large number of database operations. In general, we use command strings to perform database operations, but this method will reduce execution speed, increase network traffic and cause difficulty of modification. In order to improve the above problems, one efficient method is proposed to use the stored procedure of SQL Server to complete database operations. Through the use of stored procedure and the different methods in the development, the results show that applying stored procedure rationally in developmentrational employment of the stored procedure in develoment can effectively separate application implementation from data operation, improve operation efficiency and database access security and enhance flexibility.

Key Words:C#; WinForm; SQL; Stored Procedure

0 引言

在基于C#的WinForm+SQL应用开发中,应用程序与数据库之间存在大量数据操作,这些操作通常通过ADO.NET实现。ADO.NET是.NET框架中的一个组件库,在技术上高于现有的API。ADO.NET分为数据提供程序和数据集两个部分,实现了数据访问和数据操作的分离。其数据操作一般过程为:创建连接对象,打开与数据库的连接,通过Command类对象选择数据后把它们放到记录集中,接着处理并在服务器上更新这些数据,最后关闭它们。在该过程中,ADO.NET所提供的基础方式是将实现数据库操作的T-SQL语句以字符串的形式直接编写在C#代码中,这种方式难以满足性能优化、安全性和易维护的开发要求。除了进行SQL语句的性能调优,借助SQL Server的存储过程完成数据库操作是解决上述问题的重要方法。

1 SqlCommand对象

在ADO.NET中,对应于SQL Server提供程序的SqlCommand类对象负责执行对数据库进行操作的各种命令,包括SELECT、INSERT、UPDATE、DELETE等,一般过程为:①创建SqlCommand类对象;②将数据库操作对应的SQL语句指定给该对象的CommandText属性;③将该对象绑定到一个打开的数据库连接对象;④调用该对象的相应执行方法或将该对象绑定到DataAdapter完成数据操作。

例如:在基于C#开发的成人高等教育毕业生审核系统中,为了将成教毕业生申报数据与学信网的学生学籍数据进行一致性比对,对毕业生申报数据表与学信网的在校生学籍数据表进行了一个左外连接操作,代码如下:

DataTable checkTable=new DataTable();

SqlCommand checkConsistencyCmd=new SqlCommand(@"SELECT * FROM (SELECT ksh,xh,cm,xb,csrq,sfzh,zydm,zymc,cc,xxxs,xz,rxrq,yjbyrq,bysxjcf,xjjyt,jc FROM bmdr WHERE xjzt='在校') AS t1 LEFT OUTER JOIN(SELECT ksh,xh,xm,xb,csrq,sfzh,zydm,zymc,cc,xxxs,xz FROM zxs)as t2 ON t1.ksh=t2.ksh",adultEduConn);

SqlDataAdapter checkAda=new SqlDataAdapter(checkConsistencyCmd);

try

{

checkAda.Fill(checkTable);

}

catch(Exception ex){……}

该方式是ADO.NET提供的操作数据库基本方式,在存在大量T-SQL语句需要逐条执行的情况下至少存在以下问题:语句的逐条编译执行会降低执行速度,大量T-SQL语句的传输会占用一定的网络通信量,由于T-SQL语句是以文本的方式嵌入C#代码中的,其修改完全依赖于对应用程序的修改。

2 存储过程及应用

(1)调用存储过程进行数据库操作。 ADO.NET的命令对象可以调用存储过程完成SQL数据库的操作。存储过程建立在SQL服务器上,是一组预先编译好的T-SQL语句,由用户通过指定存储过程的名字执行。

存储过程调用与上述通过命令字符串的方式进行数据库操作在使用过程上的差异在于,前者需要事先在SQL服务器上创建存储过程,然后在SqlCommand类的对象上绑定存储过程并将对象的CommandType属性指派为“StoreProcedure”。

例如:由于成人教育的特殊性,成人在校生可能存在多个学籍,为了统计出每个毕业生是否存在重复学籍,在SQL服务器上编写如下存储过程:

create procedure chkXJCF with encryption as

begin

UPDATE bmdr SET bysxjcf=t2.d FROM (SELECT ksh AS c,t1.b AS d FROM bmdr,(SELECT sfzh AS a,count(sfzh) AS b FROM bmdr GROUP BY sfzh) AS t1 WHERE bmdr.sfzh=t1.a) AS t2 WHERE bmdr.ksh=t2.c

UPDATE bmdr SET zxsxjcf=t2.d FROM (SELECT ksh AS c,t1.b AS d FROM bmdr,(SELECT sfzh AS a,count(sfzh) AS b FROM zxs GROUP BY sfzh) AS t1 WHERE bmdr.sfzh=t1.a) AS t2 WHERE bmdr.ksh=t2.c

end

为了调用该存储过程,在C#程序中使用如下代码:

SqlCommand chkCMD=new SqlCommand(@"chkXJCF",adultEduConn);

chkCMD.CommandType=CommandType.StoreProcedure;

try{

aduleEduConn.Open();

chkCMD.ExecuteNonQuery();

}

catch(Exception ex){……}

与通过命令字符串方式进行数据库操作相比,存储过程调用好处有:存储过程在第一次调用后就驻留在内存中,不需要二次编译和优化,提升了执行性能,且由于存储过程通过指定的名字执行,降低了网络通信量;存储过程存在于SQL服务器上,完全独立于应用程序,即使出现修改需求也不影响应用程序;存储过程可以通过授权提供更高的安全性。

(2)利用存储过程实现参数化查询。 存储过程可以携带参数,并通过指定参数的方向完成应用程序中的参数化查询。由于参数是类型化的替代占位符,而非未经检查的纯文本,因此可以有效防范类似于SQL注入之类的攻击,提高安全性。除了在SQL服务器上正确编写带参数的存储过程外,还需要为SqlCommand对象增加参数,以完成参数的传递。

例如:为了将往届未通过审核的成教毕业生数据追加到本届待审核数据中,需要通过姓名查找未通过审核毕业生数据表并排除该姓名在本届待审核数据中的存在,存储过程就需要用学生的姓名作为一个输入参数完成查询。建立存储过程代码如下:

create procedure joinwith_xm (@para char(40)) with encryption as

begin

select RTRIM(ksh) AS ksh,RTRIM(xh) AS xh,RTRIM(xm) AS xm,RTRIM(xb) AS xb, sfzh, RTRIM(zydm) AS zydm, RTRIM(zymc) AS zymc, RTRIM(cc) AS cc, RTRIM(xxxs) AS xxxs,RTRIM(xz) AS xz from WBY where xm=@para and ksh not in (select ksh from bmdr where xm=@para)

……

end

为了完成该存储过程的调用,在使用SqlCommand对象时,除了对象的CommandType属性指派为“StoreProcedure”外,还应创建相关参数,并将它们附加到SqlCommand对象上:

SqlCommand joinCmd=new SqlCommand("joinwith_xm",adultEduConn);

joinCmd.CommandType=CommandType.StoreProcedure;

joinCmd.Parameters.AddWithValue("@para",searchPanel.GetXM);

SqlDataAdapter joinAda=new SqlDataAdapter(joinCmd);

try{

joinAda.Fill(joinTable);

}

catch(Exception ex){……}

3 结语

在基于C#的WinForm+SQL数据库应用开发中合理使用存储过程,能有效將应用实现与数据操作分离,提高运行效率,提高数据库访问的安全性并增强系统的灵活性。

参考文献:

[1] WILDERMUTH S. ADO.NET应用程序开发(MCTS教程)[M].北京:清华大学出版社,2010.

[2] NAGEL C. C#高级编程 [M].第9版.北京:清华大学出版社,2014.

[3] BEN-GAN I. SQL Server 2012 T-SQL基础教程[M].北京:人民邮电出版社,2013.

[4] HAMILTON B. ADO.NET3.5经典实例[M].第2版.北京:机械出版社,2009.

[5] DEITEL P J, DEITEL H M. C# 2008程序员教程[M].第3版.北京:电子工业出版社,2009.

[6] CLARKE J. SQL注入攻击与防御[M].北京:清华大学出版社,2013.

[7] FRITCHEY G, DAM S. SQL Server 2008查询性能优化[M].北京:人民邮电出版社,2010.

[8] JORGENSEN A. SQL Server 2012管理高级教程[M].第2版.北京:清华大学出版社,2011.

[9] MICHAELIS M. C#本质论[M].第2版.北京:人民邮电出版社,2009.

[10] BROWN E. Windows Forms编程实战[M].北京:机械工业出版社,2008.

(责任编辑:杜能钢)