在sql Server 数据库框架的项目中,连接数据库操作的方式有多种,大致有: 微软的数据库工厂连接方式,要另外引用Microsoft.Practices.EnterpriseLibrary.Common.dll及Microsoft.Practices.EnterpriseLibrary.Data.dll);.net DAO 连接方式,引用了自带的(System.Data.SqlClient命名空间),另外还有其它语言专用的Sqlserverjdbc驱动包。在C#项目中,大都采用引入SqlClient命名空间方式,具体的项目中的操作连接类都有不同写法。
1.常用的是三层架构分布方式:.Model,DAL,BLL,优点分工明确,把实体,业务逻辑与连接分开,适用于大中型项目。缺点:基本上是一个表对应一个Model实体类,又需要相关的DAL,BLL类,假如项目表有上百个表,工作量可想而知;如要更改业务逻辑或增加表字段需要重新编译,整个项目要重新发布。
2.支持C#的NHibernate构架方式:是对t-sql语法的封装,只需要写实体配置文件及业务逻辑块,可自动生成sql代码并执行,高效方便。缺点:业务逻辑代码编写需参照NHibernate 的API,如有复杂的业务逻辑得花时间研究API的各种语法,回避了基本的sql代码编写,经常就是会NHibernate,而不会写t-sql语句了。修改实体或业务逻辑同样需要重新编译与发布。
3.存储过程主导构架方式:侧重于数据库存储过程,业务逻辑由复杂的存储过程sql完成。优点:连接层基本不变,所有项目通用,只需动态改变存储过程参数名称,修改业务逻辑不需要重新编译与发布。缺点:数据库无法更换。
个人观点,对于无需升级到oracle数据库的sql Server项目,应采用以存储过程构架方式,省去了大量的实体及DAL封装代码,只需关注存储过程的运用,同样可以实现复杂的业务逻辑。数据处理是项目的主导,直接对数据进行操作不是很直接吗?当然写出高效而不缓慢的sql得需实践锻炼,写多了自然会提高您的sql编写能力。
下面粘出本人常用的项目sql存储过程运用方法,提供参考:
SqlClient连接方法:
--------------查询方法---------------------
/// <summary>
/// 返回实体的DataSet对象
/// </summary>
/// <param name="strNo">实体主键</param>
/// <param name="strSearch">查询条件</param>
/// <param name="strSPName">存储过程名称</param>
/// <returns></returns>
public static DataSet DisplayData(string strNo, string strSearch, string strSPName)
{
DataSet ds = new DataSet();
using (SqlConnection connection = new SqlConnection(connectionString))
{
using (SqlCommand cmd = new SqlCommand(strSPName, connection))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("chrNo", SqlDbType.VarChar, 50).Value = strNo;
cmd.Parameters.Add("chrSearch", SqlDbType.VarChar, 4000).Value = strSearch;
try
{
if (connection.State == ConnectionState.Closed)
{
connection.Open();
}
SqlDataAdapter dp = new SqlDataAdapter(cmd);
dp.Fill(ds);
}
catch
{
return null;
}
finally
{
if (connection.State == ConnectionState.Open)
{
connection.Close();
}
}
}
}
return ds;
}
----------- 新增/编辑-方法----------------
public static string SaveDataXML(string strXmlPara, string strSPName)
{
string strRet = string.Empty;
using (SqlConnection connection = new SqlConnection(connectionString))
{
using (SqlCommand cmd = new SqlCommand(strSPName, connection))
{
cmd.Parameters.Add("@chrXML", SqlDbType.NText).Value = strXmlPara;
cmd.Parameters.Add("@chrReturn", SqlDbType.VarChar, 50).Direction = ParameterDirection.Output;
try
{
if (connection.State == ConnectionState.Closed)
{
connection.Open();
}
cmd.CommandType = CommandType.StoredProcedure;
cmd.ExecuteNonQuery();
strRet = cmd.Parameters["@chrReturn"].Value.ToString();
}
catch (Exception ex)
{
strRet = ex.Message;
}
finally
{
if (connection.State == ConnectionState.Open)
{
connection.Close();
}
}
}
}
return strRet;
}
----------删除存储过程方法--------------------
public static string DeleteBase(string strNo, string strSPName)
{
string strRet = string.Empty;
using (SqlConnection connection = new SqlConnection(connectionString))
{
using (SqlCommand cmd = new SqlCommand(strSPName, connection))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("chrNo", SqlDbType.VarChar, 50).Value = strNo;
cmd.Parameters.Add("chrReturn", SqlDbType.VarChar, 1).Direction = ParameterDirection.Output;
try
{
if (connection.State == ConnectionState.Closed)
{
connection.Open();
}
cmd.ExecuteNonQuery();
strRet = cmd.Parameters["chrReturn"].Value.ToString();
}
catch (Exception ex)
{
strRet = ex.Message;
}
finally
{
if (connection.State == ConnectionState.Open)
{
connection.Close();
}
}
}
}
return strRet;
}
---------------------------------------
存储过程sql:
------------查询------------
ALTER PROCEDURE [dbo].[存储过程名称]
@chrNo varchar(50), --主键ID
@chrSearch varchar(1000) --查询条件
AS
declare @chrSql varchar(1000)
set @chrSql='
select a.* from [表名]
where 1=1
'
if isnull(@chrNo,'')<> ''
begin
set @chrSql= @chrSql+ ' and (a.主键= '''+@chrNo+''')'
end
if isnull(@chrSearch,'')<>''
begin
set @chrSql= @chrSql+ ' '+ @chrSearch
end
set @chrSql=@chrSql+' order by a.AreaID '
exec (@chrSql)
------------常用sql xml解析编辑新增------------------
ALTER proc [dbo].[存储过程名称]
@chrXML ntext,--xml文档
@chrReturn varchar(50) output--返回是否保存成功
as
declare @intFlag int--1新增,2修改
declare @intDoc int
declare @chrError varchar(500)
declare @chrTempID varchar(5)
begin
/*传入参数解析部分*/
exec sp_xml_preparedocument @intDoc OUTPUT, @chrXML
select * into ##Temp
from openxml (@intDoc, '/root/dataM',1)
with (主键 int,字段1 char(1),字段2 varchar(200),字段3 ntext)
select @intFlag=flag,@chrTempID=主键 from ##Temp
/* 逻辑判断部分*/
begin tran
if @intFlag=2--修改
update 表名 a set a.type=b.type
from ##Temp b where 表名.主键=@chrTempID
else
begin --新增
insert into capNews (type)
select a.type
from ##Temp a
select @chrTempID=@@IDENTITY from 表名 --获得自增id
end
IF @@error<>0
begin
rollback tran
set @chrError='0更新 capNews 记录失败 '
goto err
end
drop table ##Temp
exec sp_xml_removedocument @intDoc
set @chrReturn='1' +@chrTempID
commit tran
return
--返回错误信息
err:
drop table ##Temp
exec sp_xml_removedocument @intDoc
raiserror 20001@chrError
set @chrReturn='0'
return
end
------------------
--删除存储过程
ALTER PROCEDURE [dbo].[存储过程名称]
@chrNo Varchar(5), --新闻ID
@intReturn int output --返回值 1为成功 0为失败
AS
BEGIN
begin tran
delete from 表 where 主键ID=@chrNo
I @@error<>0
BEGIN
RAISERROR 20001'更新记录失败 '
SET @intReturn=0
END
SET @intReturn=1
END
------------------------------------------
页面后台调用代码:
-------------查询-----------------
DataSet ds=DisplayData("主键ID"," and a.XX=YY","[存储过程名称]");
--------------新增/编辑----------------
string strXml = "<root><dataM 主键字段='" + 值+ "'"
+ " 字段1='" + 值+ "'></dataM></root>";
string strReturn = SaveDataXML(strXml, "存储过程名称");
if (strReturn.Substring(0, 1) == "1")
{
//成功处理
}
else
{
//失败处理
}
--------删除---------------
string strReturn = DeleteBase(表主键, "删除存储过程名称");
if (strReturn.Substring(0, 1) == "1")
{
//删除成功处理
}
else
{
//删除失败处理
}
根据实际情况可转为DataTable,DataView对象,以此类推,可写出增删改查各种存储过程。我们关注两点,后台的存储过程的调用方式及数据库的存储过程编写,项目发布后,在存储过程中修改业务逻辑不影响项目运行。