C# sql Server 项目数据库连接方式探讨

时间:2022-02-06 13:40:42
                 

               在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对象,以此类推,可写出增删改查各种存储过程。我们关注两点,后台的存储过程的调用方式及数据库的存储过程编写,项目发布后,在存储过程中修改业务逻辑不影响项目运行。