序言
数据库是我们常用的存储数据的容器,网上有很多关于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
二、连接字符串
///
/// 连接字符串
///
private static readonly string connStr = ConfigurationManager.ConnectionStrings["connStr"].ConnectionString;
其中ConfigurationManager 需要添加引用
三 在SqlHelper类中编写增、删、改通用方法
3.1 在SqlHelper 类中编写增、删、改通用方法
///
/// 通用的增删改操作(普通的格式化SQL语句、带参数SQL语句、是否是存储过程)
///
/// SQL语句/存储过程名字
/// 存储过程
/// 参数
///
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;
}
- 在WindowsFrom 测试
- 在新建一个WindowsFrom 测试程序
3.2.2 将Test 程序设置成 控制台应用程序
-
-
- 在App.config 文件中添加 connectionStrings注意一定要按照截图格式写,不能有多余的空格**
-
白色圈部分 是连接数据库的 服务器名、数据库名、账户和密码。
-
-
- 添加类库引用
-
-
-
- 测试SqlHelper 类中ExecuteNonQuery 方法
- SQL语句测试 向AccountInfo 增加一个开户信息
- 测试SqlHelper 类中ExecuteNonQuery 方法
-
///
/// SQL语句添加
///
///
///
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);
}
数据库中的结果
-
-
-
- SQL语句+参数的方式 向CardBank增加一个银行卡信息
-
-
///
/// SQL语句+参数
///
///
///
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);
}
数据库中的结果
-
-
-
- 存储过程 向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中测试
///
/// 增加存储语句
///
///
///
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 参数 存储过程名字
}
数据库中的结果
-
-
-
- 存储过程 带参数返回值的存储过程
-
-
在数据库中创建一个存取记录信息的存储过程 并返回卡余额和卡姓名
-----存储过程 也可以 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中测试
///
/// 增加存储语句 带参数输出
///
///
///
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
///
/// 通用的查询操作 数据量比较大时使用 基本不占内存(推荐)
///
/// SQL语句/存储过程名字
/// 存储过程
/// 参数
///
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语句
///
/// SqlDataReader + Sql
///
///
///
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语句+参数测试
///
/// SqlDataReader +Sql+Params
///
///
///
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()
///
/// SqlDataReader +Sqls + Parama
///
///
///
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中编写查询程序
///
/// 存储过程的查询 带参数 多表查询
///
///
///
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时同时还执行查询
///
/// 单一结果查询(第一行第一列)
/// 最大特点就是执行insert、update、delete时同时还执行查询
///
/// SQL语句/存储过程名字
/// 存储过程
/// 参数
///
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 单一结果查询
///
/// 单一结果查询
///
///
///
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 一起使用
///
/// 单一结果查询&Insert
///
///
///
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表
///
/// 执行查询,查询结果填充到DataTable 只针对查询一个表的情况
///
/// QL语句/存储过程名字
/// 存储过程
/// 参数
///
DataTable 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
///
/// SQL语句获取dateTable
///
///
///
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
///
/// 参数的方式获取dateTable
///
///
///
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
///
/// 带参数的存储过程
///
///
///
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表
///
/// 执行查询,数据填充到DataSet(多个结果集)
///
/// QL语句/存储过程名字
/// 存储过程
/// 参数
///
DateSet ///
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
///
/// GetSet
///
///
///
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表名
///
/// 执行查询,数据填充到DataSet(多个结果集)返回带表名的DataSet
///
/// 表名,Sql语句的字典
///
///
public static DataSet GetDataSet(Dictionary
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
///
/// GetSetAndTableName
///
///
///
private void btnGetSetSqlAndTableName_Click(object sender, EventArgs e)
{
string sql1 = "select * from AccountInfo";
string sql2 = "select * from BankCard";
Dictionary
sqlAndTableName = new Dictionary () {
["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语句类
///
/// SQL语句类
///
public class CommandInfo
{
///
/// sql或存储过程语句
///
public string CommandText;//sql或存储过程名
///
/// 参数列表
///
public SqlParameter[] Paras; //参数列表
///
/// 是否是存储过程
///
public bool IsProcedure; //是否是存储过程
public CommandInfo()
{
}
///
/// 构造函数
///
/// SQL语句
/// 是否是存储过程
public CommandInfo(string comText, bool isProcedure = false)
{
this.CommandText = comText;
this.IsProcedure = isProcedure;
}
///
/// 构造函数
///
/// SQL 语句
/// 是否是存储过程
/// 参数数组
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()
///
/// 事务 批量执行 CommandInfo 包括sql,脚本类型,参数列表 **********
///
/// SQL语句类列表
///
public static bool ExecuteTrans(List
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语句事务
///
/// SQL语句事务
///
///
///
private void btnExecuteTransSql_Click(object sender, EventArgs e)
{
List
cmdList = new List () {
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语句
///
/// 存储过程& SQL+参数
///
///
///
private void btnExecuteTransParasProc_Click(object sender, EventArgs e)
{
List
cmdList = new List () {
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个小时,但是收获颇丰。也给快要上一年级的小朋友做个表率。
- 在WindowsFrom 测试
- 新建一个类库 DbUtility
- 表关系图
- 创建 三个表 AccountInfo 账户信息表 BankCard 银行卡表 BankCard 转账信息表
还没有评论,来说两句吧...