C# SqlHelper 详解(自己总结)

序言

数据库是我们常用的存储数据的容器,网上有很多关于SqlHelper 类库,里面有的写的很复杂很详细(有点冗余),有很多方法基本上用不到,所以自己根据很多的项目实践总结了一套适合自己的SqlHelper 类 包括 数据库的增、删、改、查、存储过程、事务等,以便后续使用,希望能给诸君有些帮助,如有错误麻烦请指出并纠正。

数据库的创建

  • 创建一个银行信息数据

use master

--- 判断 系统是否有数据库

if exists(select * from sys.databases where name = 'DBBank')

     drop database DBBank

--- 创建数据库

create database DBBank

on ---数据文本

(

     name = 'DBBank',    --逻辑名称

     filename = 'D:\C#\CommonLib\SQL\Data\DBBank.mdf',   --物理路径和名称

     size = 5MB,    -- 文件的初始大小

     filegrowth = 2MB   --文件的增长方式可以写大小,也可以写百分比

)

log on

(

   name = 'DBBank_log',

   filename = 'D:\C#\CommonLib\SQL\Data\DBBank_log.ldf',  --日志后缀 .ldf

   size = 5MB,

   filegrowth = 2MB

)

go

  • 创建 三个表 AccountInfo 账户信息表   BankCard 银行卡表   BankCard 转账信息表

use DBBank

-- 判断 表 AccountInfo 是否存在

if exists(select * from sys.objects where  name = 'AccountInfo' and type = 'U')

     drop table AccountInfo

go

Create table AccountInfo   --建表  账户信息表

(

     AccountId int primary key,    --账户Id 主键

     AccountCode varchar(20) check(len(AccountCode) = 18) unique,   -- 身份证号码 检查长度并且唯一

     AccountPhone varchar(11) check(len(AccountPhone) = 11),        --电话号码

     RealName nvarchar(10) not null,            --姓名

     OpenTime smalldatetime default(getdate())  --开户时间

)

if exists(select * from sys.objects where name = 'BankCard' and type = 'U')

     drop table BankCard

create table BankCard      --创建 银行卡表

(

     CardNo varchar(30) primary key ,     ---创建卡号 主键

     AccountId int not null,                   --账户编号(与账户信息表形成外键关系)

     CardPwd varchar(20) not null,      --账户密码

     CardMoney money check(CardMoney >= 0) NOT NULL,     --余额

     CardTime smalldatetime default(getdate())    --建卡时间

)

if exists(select * from sys.objects where name = 'CardExchange' and type = 'U')

     drop table CardExchange

create table CardExchange     --创建 转账信息表

(

     ExchangeId int primary key identity(1,1),     --交易自动编号

     CardNo varchar(30) not null,    --银行卡号

     MoneyInBank money ,    --存钱金额

     MoneyOutBank money,   --取钱金额

     ExchangeTime smalldatetime default(getdate())    --交易时间

)

  • 表关系图

SqlHelper类库编写

  • 新建一个类库 DbUtility

在类库中新建一个类 SqlHelper

二、连接字符串

/// <summary>

/// 连接字符串

/// </summary>

private static readonly string connStr = ConfigurationManager.ConnectionStrings["connStr"].ConnectionString;

其中ConfigurationManager 需要添加引用

三 在SqlHelper类中编写增、删、改通用方法

3.1 在SqlHelper 类中编写增、删、改通用方法

 /// <summary>

/// 通用的增删改操作(普通的格式化SQL语句、带参数SQL语句、是否是存储过程)

/// </summary>

/// <param name="sql">SQL语句/存储过程名字</param>

/// <param name="isProcedure">存储过程</param>

/// <param name="paras">参数</param>

/// <returns></returns>

public static int ExecuteNonQuery(string sql,bool isProcedure = false, params SqlParameter[] paras)

{

    //select @@Identity 返回上一次插入记录时自动产生的ID

    int result = 0;

    SqlConnection conn = new SqlConnection(connStr);  //连接字符串

    try

    {

        if(conn == null)

            throw new ArgumentNullException("连接对象不能为空!");

        SqlCommand cmd = new SqlCommand(sql, conn);

        if(isProcedure)

            cmd.CommandType = CommandType.StoredProcedure;   //SqlCommand 设置成存储过程

        if (conn.State == ConnectionState.Closed)

            conn.Open();   //打开数据库               

        if (paras != null && paras.Length > 0)

        {

            cmd.Parameters.Clear(); //清空上一个数据

            cmd.Parameters.AddRange(paras); //添加本次数据

        }

        result = cmd.ExecuteNonQuery();

    }

    catch (Exception ex)

    {

        //如果有必要在这里写个记录日志

        string errorMessage = "调用ExecuteNonQuery方法发生异常:"+ex.Message;

        throw new Exception(errorMessage);

    }

    finally    //不管前面异常都会执行

    {

        conn.Close();

    }

    return result;

}

  1. 在WindowsFrom 测试
    1. 在新建一个WindowsFrom 测试程序

3.2.2  将Test 程序设置成 控制台应用程序

      1. 在App.config 文件中添加 connectionStrings注意一定要按照截图格式写,不能有多余的空格**

白色圈部分 是连接数据库的 服务器名、数据库名、账户和密码。

      1. 添加类库引用

      1. 测试SqlHelper 类中ExecuteNonQuery 方法
        1. SQL语句测试  向AccountInfo 增加一个开户信息

  /// <summary>

 /// SQL语句添加

 /// </summary>

 /// <param name="sender"></param>

 /// <param name="e"></param>

 private void btnAdd_Click(object sender, EventArgs e)

 {

     string sql = "insert into AccountInfo(AccountId,AccountCode,AccountPhone,RealName,Opentime)values(1,'320833200010112222','12345678900','李*','2021-12-18')";

     int i = SqlHelper.ExecuteNonQuery(sql, false, null);

 }

数据库中的结果

        1. SQL语句+参数的方式  向CardBank增加一个银行卡信息

 /// <summary>

/// SQL语句+参数

/// </summary>

/// <param name="sender"></param>

/// <param name="e"></param>

private void btnAddParas_Click(object sender, EventArgs e)

{

    string sql = "insert into BankCard(CardNo,AccountId,CardPwd,CardMoney,CardTime)values" +

        "(@CardNo,@AccountId,@CardPwd,@CardMoney,@CardTime)";

    SqlParameter[] paras = new SqlParameter[]

    {

        new SqlParameter("@CardNo","6225125478544111"),

        new SqlParameter("@AccountId",1),   //注意 值类型不能为 0 ,如果是0 则需要装箱(object)0

        new SqlParameter("@CardPwd","888888"),

        new SqlParameter("@CardMoney",1000),

        new SqlParameter("CardTime",DateTime.Now.ToString())

    };

    int i = SqlHelper.ExecuteNonQuery(sql, false, paras);

}

数据库中的结果

        1. 存储过程  向AccountInfo 增加一个开户信息

在数据库中创建一个存取记录信息的存储过程

-----存储过程  也可以 proc    有参数输入无参数输出

if exists(select * from sys.objects where name = 'proc_AddCardExchange')

     drop procedure proc_AddCardExchange

go

create procedure proc_AddCardExchange

--存储过程输入参数的定义

@CardNo varchar(30),

@MoneyInBank money,

@MoneyOutBank money,

@ExchangeTime smalldatetime

as

---添加交易记录

     insert into CardExchange(CardNo,MoneyInBank,MoneyOutBank,ExchangeTime)values(@CardNo,@MoneyInBank,@MoneyOutBank,@ExchangeTime)

--- 跟新银行卡信息

     update BankCard set CardMoney = CardMoney + @MoneyInBank - @MoneyOutBank where CardNo = @CardNo

go

在WindowsFrom中测试

/// <summary>

/// 增加存储语句

/// </summary>

/// <param name="sender"></param>

/// <param name="e"></param>

private void btnAddProc_Click(object sender, EventArgs e)

{

    SqlParameter[] paras = new SqlParameter[]

    {

        new SqlParameter("@CardNo","6225125478544111"),

        new SqlParameter("@MoneyInBank",120),

        new SqlParameter("@MoneyOutBank",(object)0),  //注意 值类型不能为 0 ,如果是0 则需要装箱成引用类型 (object)0

        new SqlParameter("@ExchangeTime",DateTime.Now.ToString())

    };

    int i = SqlHelper.ExecuteNonQuery("proc_AddCardExchange",true,paras);  //sql 参数 存储过程名字

}

数据库中的结果

        1. 存储过程 带参数返回值的存储过程

在数据库中创建一个存取记录信息的存储过程 并返回卡余额和卡姓名

-----存储过程  也可以 proc    有参数输入有参数输出

if exists(select * from sys.objects where name = 'proc_AddCardExchangeShowUse')

     drop procedure proc_AddCardExchangeShowUse

go

create proc proc_AddCardExchangeShowUse

--存储过程参数定义

@CardNo varchar(30),

@MoneyInBank money,

@MoneyOutBank money,

@ExchangeTime smalldatetime,

@RealName nvarchar(10) output,

@CardMoney money output

as

     ---添加交易记录

     insert into CardExchange(CardNo,MoneyInBank,MoneyOutBank,ExchangeTime)values(@CardNo,@MoneyInBank,@MoneyOutBank,@ExchangeTime)

    --- 跟新银行卡信息

     update BankCard set CardMoney = CardMoney + @MoneyInBank - @MoneyOutBank where CardNo = @CardNo

     --- 获取输出参数

     select @CardMoney = BankCard.CardMoney, @RealName = AccountInfo.RealName from BankCard

     inner join AccountInfo on AccountInfo.AccountId = BankCard.AccountId

     where BankCard.CardNo = @CardNo

go

在WindowsFrom中测试

  /// <summary>

        /// 增加存储语句 带参数输出

        /// </summary>

        /// <param name="sender"></param>

        /// <param name="e"></param>

        private void btnAddProcOut_Click(object sender, EventArgs e)

        {

            SqlParameter outPar = new SqlParameter("@RealName", SqlDbType.NVarChar,10);  //字符一定要写明长度

            SqlParameter outPar2 = new SqlParameter("@CardMoney", SqlDbType.Money);

            outPar.Direction = ParameterDirection.Output;      //设置输出参数

            outPar2.Direction = ParameterDirection.Output;

            SqlParameter[] paras = new SqlParameter[]

            {

                new SqlParameter("@CardNo","6225125478544111"),

                new SqlParameter("@MoneyInBank",80),

                new SqlParameter("@MoneyOutBank",(object)0),  //注意 值类型不能为 0 ,如果是0 则需要装箱成引用类型 (object)0

                new SqlParameter("@ExchangeTime",DateTime.Now.ToString()),

                outPar,

                outPar2

            };

            int i = SqlHelper.ExecuteNonQuery("proc_AddCardExchangeShowUse", true, paras); //sql 参数 存储过程名字

            if (i >= 1)

            {

                string realName = outPar.Value.ToString();

                double money = Convert.ToDouble(outPar2.Value);

                Console.WriteLine("姓名:" + realName + "\t" + "余额:" + money);

            }          

        }

测试结果

四 在SqlHelper类中编写查询方法

4.1 SqlDataReader 查询  ExecuteReader

/// <summary>

/// 通用的查询操作 数据量比较大时使用 基本不占内存(推荐)

/// </summary>

/// <param name="sql">SQL语句/存储过程名字</param>

/// <param name="isProcedure">存储过程</param>

/// <param name="parameters">参数</param>

/// <returns></returns>

public static SqlDataReader ExecuteReader(string sql, bool isProcedure = false, params SqlParameter[] paras)

{

    SqlConnection conn = new SqlConnection(connStr);  //连接字符串

    SqlDataReader reader = null;

    try

    {

        if (conn == null)

            throw new ArgumentNullException("连接对象不能为空!");

        SqlCommand cmd = new SqlCommand(sql, conn);

        if (isProcedure)

            cmd.CommandType = CommandType.StoredProcedure;   //SqlCommand 设置成存储过程

        if (conn.State == ConnectionState.Closed)

            conn.Open();   //打开数据库               

        if (paras != null && paras.Length > 0)

        {

            cmd.Parameters.Clear(); //清空上一个数据

            cmd.Parameters.AddRange(paras); //添加本次数据

        }

        //在执行该命令时,如果关闭关联的DataReader对象,则关联的Connenction对象也将关闭。******

        reader = cmd.ExecuteReader(CommandBehavior.CloseConnection);

    }

    catch (Exception ex)

    {

        //次处可以添加日志

        string errorMessage = "调用ExecuteReader方法发生异常,具体异常信息:" + ex.Message;

        conn.Close();

        throw new Exception(errorMessage);

    }

    return reader;

}

4.1.1  在WindowsFrom中测试

4.1.1.1  SQL语句

/// <summary>

/// SqlDataReader  + Sql

/// </summary>

/// <param name="sender"></param>

/// <param name="e"></param>

private void btnReader_Click(object sender, EventArgs e)

{

    string sql = "select * from BankCard";

    SqlDataReader reader = SqlHelper.ExecuteReader(sql, false);

    while(reader.Read())

    {

        Console.WriteLine("卡号:" + reader["CardNo"] + "\t" + "余额:" + reader["CardMoney"]);

    }

    reader.Close();    //一定要关闭SqlDataReader

}

测试结果

4.1.1.2  SQL语句+参数测试

/// <summary>

/// SqlDataReader +Sql+Params

/// </summary>

/// <param name="sender"></param>

/// <param name="e"></param>

private void btnReaderParms_Click(object sender, EventArgs e)

{

    string sql = "select * from BankCard where CardNo = @CardNo";

    SqlParameter[] paras = new SqlParameter[]

    {

        new SqlParameter("@CardNo","6225125478544111")

    };

    SqlDataReader reader = SqlHelper.ExecuteReader(sql,false, paras);

    while(reader.Read())

    {

        Console.WriteLine("卡号:" + reader["CardNo"] + "\t" + "余额:" + reader["CardMoney"]);

    }

    reader.Close();     //一定要关闭SqlDataReader

}

测试结果

4.1.1.3  SQL语句+参数测试 多表查询   reader.NextResult()

/// <summary>

/// SqlDataReader +Sqls + Parama

/// </summary>

/// <param name="sender"></param>

/// <param name="e"></param>

private void btnDataReaderParamss_Click(object sender, EventArgs e)

{

    //注意*****两个语句连接用;

    string sql = "select * from BankCard where CardNo = @CardNo"+";"+ "select * from AccountInfo where AccountId = @AccountId";

    SqlParameter[] paras = new SqlParameter[]

    {

        new SqlParameter("@CardNo","6225125478544111"),

        new SqlParameter("@AccountId",1)

    };

    SqlDataReader reader = SqlHelper.ExecuteReader(sql, false, paras);

    while (reader.Read())

    {

        Console.WriteLine("卡号:" + reader["CardNo"] + "\t" + "余额:" + reader["CardMoney"]);

    }

    if(reader.NextResult()) //跳转到下一个结果集(当读取批处理Transact-SQL 语句的结果时,使数据读取器前进到下一个结果)

    {

        while(reader.Read())

        {

            Console.WriteLine("姓名:" + reader["RealName"]);

        }

    }

    reader.Close();     //一定要关闭SqlDataReader

}

测试结果

4.1.1.4  存储过程

4.1.1.4.1  在数据库中创建一个查询账户信息变化记录

if exists(select * from sys.objects where name = 'proc_SelectCardExchangeParas')

     drop procedure proc_SelectCardExchangeParas

go

create procedure proc_SelectCardExchangeParas

@CardNo varchar(30)

as

     select CardNo,CardMoney from BankCard where CardNo = @CardNo

     select MoneyInBank,MoneyOutBank,ExchangeTime from CardExchange where CardNo = @CardNo

     select RealName from AccountInfo inner join BankCard on  AccountInfo.AccountId = BankCard.AccountId where BankCard.CardNo = @CardNo

go

4.1.1.4.2  在WF中编写查询程序

/// <summary>

/// 存储过程的查询 带参数 多表查询

/// </summary>

/// <param name="sender"></param>

/// <param name="e"></param>

private void btnDataReaderProcParas_Click(object sender, EventArgs e)

{

    string sql = "proc_SelectCardExchangeParas";

    SqlParameter[] paras = new SqlParameter[]

    {

        new SqlParameter("@CardNo","6225125478544111")

    };

    SqlDataReader reader = SqlHelper.ExecuteReader(sql, true, paras);

    while (reader.Read())

    {

        Console.WriteLine("卡号:" + reader["CardNo"] + "\t" + "余额:" + reader["CardMoney"]);

    }

    Console.WriteLine("************************华丽的分割线*****************************");

    if(reader.NextResult()) //跳转到下一个结果集(当读取批处理Transact-SQL 语句的结果时,使数据读取器前进到下一个结果)

    {

        while(reader.Read())

        {

            Console.WriteLine("存钱:" + reader["MoneyInBank"] + "\t" + "取钱:" + reader["MoneyOutBank"] + "\t" + "交易时间:" + reader["ExchangeTime"]);

        }

    }

    Console.WriteLine("************************华丽的分割线*****************************");

    if(reader.NextResult())

    {

        while(reader.Read())

        {

            Console.WriteLine("姓名:" + reader["RealName"]);

        }

    }

    reader.Close();     //一定要关闭SqlDataReader

}

测试结果

4.2  单一结果查询 ExecuteScalar() 返回第一行第一列,最大的特点是执行insert、update、delete时同时还执行查询

/// <summary>

/// 单一结果查询(第一行第一列)

/// 最大特点就是执行insert、update、delete时同时还执行查询

/// </summary>

/// <param name="sql">SQL语句/存储过程名字</param>

/// <param name="isProcedure">存储过程</param>

/// <param name="paras">参数</param>

/// <returns></returns>

public static object ExecuteScalar(string sql, bool isProcedure = false, params SqlParameter[] paras)

{

    SqlConnection conn = new SqlConnection(connStr);

    try

    {

        if (conn == null)

            throw new ArgumentNullException("连接对象不能为空!");

        SqlCommand cmd = new SqlCommand(sql, conn);

        if (isProcedure)

            cmd.CommandType = CommandType.StoredProcedure;   //SqlCommand 设置成存储过程

        if (conn.State == ConnectionState.Closed)

            conn.Open();   //打开数据库                

        if (paras != null && paras.Length > 0)

        {

            cmd.Parameters.Clear(); //清空上一个数据

            cmd.Parameters.AddRange(paras); //添加本次数据

        }

        return cmd.ExecuteScalar();

    }

    catch(Exception ex)

    {

        //如果有必要在这里写个记录日志

        string errorMessage = "调用ExecuteScalar方法发生异常:" + ex.Message;

        throw new Exception(errorMessage);

    }

    finally

    {

        conn.Close();

    }

}

4.2.1  在WF中测试

4.2.1.1  单一结果查询

/// <summary>

/// 单一结果查询

/// </summary>

/// <param name="sender"></param>

/// <param name="e"></param>

private void btnExecuteScalar_Click(object sender, EventArgs e)

{

    string str = "select CardMoney from BankCard";

    object o = SqlHelper.ExecuteScalar(str,false,null);

    if (o != null)

    {

        Console.WriteLine(o.ToString());

    }

}

测试结果

4.2.1.1  单一结果查询配合Insert into 一起使用

/// <summary>

/// 单一结果查询&Insert

/// </summary>

/// <param name="sender"></param>

/// <param name="e"></param>

private void btnExecuteScalarAddInsert_Click(object sender, EventArgs e)

{

    string sql = "insert into AccountInfo(AccountId,AccountCode,AccountPhone,RealName,Opentime)" +

        "values(2,'320833200010116222','12345678922','小二','2022-12-19')" + ";" + "select count(*) from AccountInfo";

    object o = SqlHelper.ExecuteScalar(sql,false,null);

    Console.WriteLine((int)o);

}

测试结果

4.3  单表查询 GetDataTable 返回一张DataTable表

/// <summary>

/// 执行查询,查询结果填充到DataTable 只针对查询一个表的情况

/// </summary>

/// <param name="sql">QL语句/存储过程名字</param>

/// <param name="isProcedure">存储过程</param>

/// <param name="paras">参数</param>

/// <returns>DataTable</returns>

public static DataTable GetDataTable(string sql, bool isProcedure = false, params SqlParameter[] paras)

{

    DataTable dt = null;

    SqlConnection conn = new SqlConnection (connStr);

    try

    {

        if (conn == null)

            throw new ArgumentNullException("连接对象不能为空!");

        SqlCommand cmd = new SqlCommand(sql, conn);

        if (isProcedure)

            cmd.CommandType = CommandType.StoredProcedure;   //SqlCommand 设置成存储过程

        if (conn.State == ConnectionState.Closed)

            conn.Open();   //打开数据库               

        if (paras != null && paras.Length > 0)

        {

            cmd.Parameters.Clear(); //清空上一个数据

            cmd.Parameters.AddRange(paras); //添加本次数据

        }

        SqlDataAdapter da = new SqlDataAdapter(cmd);    //实例化一个数据库数据适配器类

        dt = new DataTable();

        da.Fill(dt);

        cmd.Parameters.Clear();

    }

    catch (Exception ex)

    {

        //如果有必要在这里写个记录日志

        string errorMessage = "调用GetDataTable方法发生异常:" + ex.Message;

        throw new Exception(errorMessage);

    }

    finally

    {

        conn.Close();

    }

    return dt;

}

4.3.1  在WF中测试

4.3.1.1  SQL语句获取DataTable

/// <summary>

/// SQL语句获取dateTable

/// </summary>

/// <param name="sender"></param>

/// <param name="e"></param>

private void btnGetDataTableSQL_Click(object sender, EventArgs e)

{

    string sql = "select * from AccountInfo";

    DataTable dt = SqlHelper.GetDataTable(sql, false, null);

    if (dt != null)

    {

        foreach(DataRow dr in dt.Rows)

        {

            Console.WriteLine("名字:" + dr["RealName"].ToString() + "\t" + "身份证:" + dr["AccountCode"].ToString());

        }              

    }

}

测试结果

4.3.1.2  SQL语句+参数 获取DataTable

/// <summary>

/// 参数的方式获取dateTable

/// </summary>

/// <param name="sender"></param>

/// <param name="e"></param>

private void btnGetDataTableParams_Click(object sender, EventArgs e)

{

    string sql = "select * from AccountInfo where AccountId >= @AccountId";

    SqlParameter[] paras = new SqlParameter[]

    {

        new SqlParameter("@AccountId",2)

    };

    DataTable dt = SqlHelper.GetDataTable(sql,false,paras);

    if(dt != null)

    {

        foreach(DataRow dr in dt.Rows)

        {

            Console.WriteLine("名字:" + dr["RealName"].ToString() + "\t" + "身份证:" + dr["AccountCode"].ToString());

        }

    }

}

测试结果

4.3.1.3  存储语句+参数 获取DataTable

/// <summary>

/// 带参数的存储过程

/// </summary>

/// <param name="sender"></param>

/// <param name="e"></param>

private void btnGetDataTableProcParas_Click(object sender, EventArgs e)

{

    SqlParameter[] paras = new SqlParameter[]

    {

        new SqlParameter("@CardNo","6225125478544111")

    };

    DataTable dt = SqlHelper.GetDataTable("proc_SelectCardExchangeParas", true, paras);

    if (dt != null)

    {

        foreach (DataRow dr in dt.Rows)

        {

            Console.WriteLine("卡号:" + dr["CardNo"].ToString() + "\t" + "余额:" + dr["CardMoney"].ToString());

        }

    }

}

测试结果

4.4  多表查询 GetDataSet 返回一张或多张DataTable表

/// <summary>

/// 执行查询,数据填充到DataSet(多个结果集)

/// </summary>

/// <param name="sql">QL语句/存储过程名字</param>

/// <param name="isProcedure">存储过程</param>

/// <param name="paras">参数</param>

/// <returns>DateSet</returns>

/// <exception cref="Exception"></exception>

public static DataSet GetDataSet(string sql, bool isProcedure = false, params SqlParameter[] paras)

{

    DataSet ds = null;

    SqlConnection conn = new SqlConnection(connStr);

    try

    {

        if (conn == null)

            throw new ArgumentNullException("连接对象不能为空!");

        SqlCommand cmd = new SqlCommand(sql, conn);

        if (isProcedure)

            cmd.CommandType = CommandType.StoredProcedure;   //SqlCommand 设置成存储过程

        if (conn.State == ConnectionState.Closed)

            conn.Open();   //打开数据库               

        if (paras != null && paras.Length > 0)

        {

            cmd.Parameters.Clear(); //清空上一个数据

            cmd.Parameters.AddRange(paras); //添加本次数据

        }

        SqlDataAdapter da = new SqlDataAdapter(cmd);    //实例化一个数据库数据适配器类

        ds = new DataSet();

        da.Fill(ds);

        cmd.Parameters.Clear();

    }

    catch (Exception ex)

    {

        //如果有必要在这里写个记录日志

        string errorMessage = "调用GetDataSet方法发生异常:" + ex.Message;

        throw new Exception(errorMessage);

    }

    finally

    {

        conn.Close();

    }

    return ds;

}

4.4.1  在WF中测试

4.4.1.1  SQL语句获取DataSet

/// <summary>

/// GetSet

/// </summary>

/// <param name="sender"></param>

/// <param name="e"></param>

private void btnGetSetSql_Click(object sender, EventArgs e)

{

    string sql = "select * from AccountInfo" + ";" + "select * from BankCard";

    DataSet ds = SqlHelper.GetDataSet(sql);

    foreach(DataRow dr in ds.Tables[0].Rows)

    {

        Console.WriteLine("名字:" + dr["RealName"].ToString() + "\t" + "身份证:" + dr["AccountCode"].ToString());

    }

    foreach(DataRow dr in ds.Tables[1].Rows)

    {

        Console.WriteLine("卡号:" + dr["CardNo"].ToString() + "\t" + "余额:" + dr["CardMoney"].ToString());

    }

}

测试结果

4.5  多表查询 GetDataSet 返回一张或多张 包含DataTable表名

/// <summary>

/// 执行查询,数据填充到DataSet(多个结果集)返回带表名的DataSet

/// </summary>

/// <param name="sqlAndTableName">表名,Sql语句的字典</param>

/// <returns></returns>

/// <exception cref="Exception"></exception>

public static DataSet GetDataSet(Dictionary<string,string> sqlAndTableName)

{

    SqlConnection conn = new SqlConnection(connStr);

    SqlCommand cmd = new SqlCommand();

    DataSet ds = null;

    try

    {

        if (conn == null)

            throw new ArgumentNullException("连接对象不能为空!");

        if (conn.State == ConnectionState.Closed)

            conn.Open();   //打开数据库

        if (sqlAndTableName == null)

            throw new ArgumentException("连接数据库字符串不能为空!");

        cmd.Connection = conn;

        SqlDataAdapter sd = new SqlDataAdapter(cmd);   实例化一个数据库数据适配器类

        ds = new DataSet();       //实例化 DataSet

        foreach(string tableName in sqlAndTableName.Keys)

        {

            cmd.CommandText = sqlAndTableName[tableName];

            sd.Fill(ds,tableName);

        }

        return ds;

    }

    catch (Exception ex)

    {

        //如果有必要在这里写个记录日志

        string errorMessage = "调用GetDataSet方法发生异常:" + ex.Message;

        throw new Exception(errorMessage);

    }

    finally

    {

        conn.Close();

    }

}

4.5.1  在WF中测试

4.5.1.1  SQL语句获取DataSet

/// <summary>

/// GetSetAndTableName

/// </summary>

/// <param name="sender"></param>

/// <param name="e"></param>

private void btnGetSetSqlAndTableName_Click(object sender, EventArgs e)

{

    string sql1 = "select * from AccountInfo";

    string sql2 = "select * from BankCard";

    Dictionary<string, string> sqlAndTableName = new Dictionary<string, string>()

    {

        ["AccountInfo"] = sql1, //键 值

        ["BankCard"] = sql2

    };

    DataSet ds = SqlHelper.GetDataSet(sqlAndTableName);

    foreach (DataRow dr in ds.Tables["AccountInfo"].Rows)

    {

        Console.WriteLine("名字:" + dr["RealName"].ToString() + "\t" + "身份证:" + dr["AccountCode"].ToString());

    }

    foreach (DataRow dr in ds.Tables["BankCard"].Rows)

    {

        Console.WriteLine("卡号:" + dr["CardNo"].ToString() + "\t" + "余额:" + dr["CardMoney"].ToString());

    }

}

测试结果

五 在SqlHelper类中编写事务方法

5.1 在DbUtility类库中编写一个SQL语句类

/// <summary>

/// SQL语句类

/// </summary>

public class CommandInfo

{

    /// <summary>

    /// sql或存储过程语句

    /// </summary>

    public string CommandText;//sql或存储过程名

    /// <summary>

    /// 参数列表

    /// </summary>

    public SqlParameter[] Paras; //参数列表

    /// <summary>

    /// 是否是存储过程

    /// </summary>

    public bool IsProcedure; //是否是存储过程

    public CommandInfo()

    {

    }

    /// <summary>

    /// 构造函数

    /// </summary>

    /// <param name="comText">SQL语句</param>

    /// <param name="isProc">是否是存储过程</param>

    public CommandInfo(string comText, bool isProcedure = false)

    {

        this.CommandText = comText;

        this.IsProcedure = isProcedure;

    }

    /// <summary>

    /// 构造函数

    /// </summary>

    /// <param name="sqlText">SQL 语句</param>

    /// <param name="isProc">是否是存储过程</param>

    /// <param name="para">参数数组</param>

    public CommandInfo(string sqlText, bool isProcedure = false, params SqlParameter[] paras)

    {

        this.CommandText = sqlText;

        this.Paras = paras;

        this.IsProcedure = isProcedure;

    }

}

5.2 在SqlHelper类中 ExecuteTrans 事务方法

调取事务需要5步骤

1、开启事务   实例化事务

2、将创建的SqlTransaction对象分配给要执行的SqlCommand的Transaction属性  

3、调用相应的方法执行SqlCommand命令(循环调用)

4、如果所有的sql命令都执行成功,则执行commit这个方法,提交事务

5、如果执行异常回滚 Rollback()

/// <summary>

/// 事务 批量执行 CommandInfo 包括sql,脚本类型,参数列表 **********

/// </summary>

/// <param name="comList">SQL语句类列表</param>

/// <returns></returns>

public static bool ExecuteTrans(List<CommandInfo> comList)

{

    SqlConnection conn = new SqlConnection(connStr);

    SqlCommand cmd = new SqlCommand();

    SqlTransaction trans = null;          

    try

    {

        if (conn == null)

            throw new ArgumentNullException("连接对象不能为空!");

        if (conn.State == ConnectionState.Closed)

            conn.Open();   //打开数据库

        if (comList == null)

            throw new ArgumentNullException("连接语句不能为空!");

        //1、开启事务

        先实例SqlTransaction类,使用这个事务使用的是conn 这个连接,使用BeginTransaction这个方法来开始执行这个事务

        trans = conn.BeginTransaction(); //执行数据库事务

        //2、将创建的SqlTransaction对象分配给要执行的SqlCommand的Transaction属性              

        cmd.Transaction = trans;

        cmd.Connection = conn;

        int count = 0;

        for (int i = 0; i < comList.Count; i++)

        {

            //存储过程语句

            //3、调用相应的方法执行SqlCommand命令

            cmd.CommandText = comList[i].CommandText;

            if (comList[i].IsProcedure)  //是存储过程

                cmd.CommandType = CommandType.StoredProcedure;

            else

                cmd.CommandType = CommandType.Text; //语句

            if (comList[i].Paras != null && comList[i].Paras.Length > 0)

            {

                cmd.Parameters.Clear();

                foreach (var p in comList[i].Paras)

                {

                    cmd.Parameters.Add(p);

                }

            }

            count += cmd.ExecuteNonQuery();

        }

        //4、如果所有的sql命令都执行成功,则执行commit这个方法,执行这些操作

        trans.Commit();

        return true;

    }

    catch (Exception ex)

    {

        //5、 异常回滚

        trans.Rollback();

        //如果有必要在这里写个记录日志

        string errorMessage = "调用ExecuteTrans方法发生异常:" + ex.Message;

        throw new Exception(errorMessage);

    }

    finally

    {

        if (cmd.Transaction != null)

            cmd.Transaction = null;    //清空事务

        conn.Close();

    }

}

5.2.1  在WF中测试

5.2.1.1  SQL语句事务

/// <summary>

 /// SQL语句事务

 /// </summary>

 /// <param name="sender"></param>

 /// <param name="e"></param>

 private void btnExecuteTransSql_Click(object sender, EventArgs e)

 {

     List<CommandInfo> cmdList = new List<CommandInfo>()

     {

         new CommandInfo("update BankCard set CardMoney = CardMoney - 100 where CardNo = '6225125478544111'",false),

         new CommandInfo("insert into CardExchange(CardNo,MoneyInBank,MoneyOutBank,ExchangeTime)values('6225125478544111',0,100,'2023-10-1')")

     };

     bool b = SqlHelper.ExecuteTrans(cmdList);

     Console.WriteLine(b);

 }

测试结果

5.2.1.2  存储过程+带参数的SQL语句

/// <summary>

/// 存储过程& SQL+参数

/// </summary>

/// <param name="sender"></param>

/// <param name="e"></param>

private void btnExecuteTransParasProc_Click(object sender, EventArgs e)

{

    List<CommandInfo> cmdList = new List<CommandInfo>()

    {

        new CommandInfo("insert into AccountInfo(AccountId,AccountCode,AccountPhone,RealName,Opentime)values(@AccountId,@AccountCode,@AccountPhone,@RealName,@Opentime)",

            false, new SqlParameter[]

            {

                new SqlParameter("@AccountId",3),

                new SqlParameter("@AccountCode","320833200010113333"),

                new SqlParameter("@AccountPhone","12345678933"),

                new SqlParameter("@RealName","张三"),

                new SqlParameter("@OpenTime","2022-01-01")

            }),  //SQL + 参数

        new CommandInfo("proc_AddCardExchange", true, new SqlParameter[]

        {

            new SqlParameter("@CardNo","6225125478544111"),

            new SqlParameter("@MoneyInBank",300),

            new SqlParameter("@MoneyOutBank",(object)0),

            new SqlParameter("@ExchangeTime","2024-01-01")

        }),

    };

    bool b = SqlHelper.ExecuteTrans(cmdList);

    Console.WriteLine(b);

}

测试结果

总结

    数据库的SqlHelper类 主要由 增删改的 ExecuteNonQuery 方法, 查询的 ExecuteReader 方法(大数据读取)、ExecuteScalar 方法 读单一结果查询,同时可以执行增删改语句、GetDataTable 方法 单表查询、GetDataSet 方法多表查询 以及事务操作ExecuteTrans 方法组成, 写这篇文章的时候也重温了数据库的一些语法,以及对存储过程和事务有了更进一步的了解。虽然花了7-8个小时,但是收获颇丰。也给快要上一年级的小朋友做个表率。

  • 18
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值