ADO.NET 封装 SqlHelper
开发工具:Visual Studio 2019
需要的包
System.Data.SqlClient
ADO.NET的类及主要成员
- Connection:用来连接数据库,常用方法
Open()
使用示例
string conString="连接字符串";
string sql="sql语句";
//不使用C# 8.0 的using新语法
using(SqlConnection con = new SqlConnection(conString))
{
using(SqlCommand cmd = new SqlCommand(sql,con))
{
//若使用无参构造
//cmd.CommandText = sql;
//cmd.Connection = con;
//推荐:连接对象,最晚打开,最早关闭,节省资源
//用前打开连接,用完立刻关闭连接
con.Open();
Console.WriteLine("打开连接成功");
//省略数据库操作
}
Console.WriteLine("关闭连接,释放资源");
}
- Command:用来执行SQL语句,常用方法
-
ExecuteNonQuery()
:Insert、delete、update语句时使用
返回int类型,表示执行SQL语句后,所影响的行数,只有执行Insert、delete、update语句时,才会返回所影响的行数,执行任何其它SQL语句永远返回-1 -
ExcuteScalar()
:当执行返回单个结果的时候(一行一列,如COUNT函数)时使用,执行聚合函数不返回null(COUNT最少返回0),执行的不是聚合函数,可能返回null,要判断 -
ExecuteReader()
:当查询出多行多列结果的时候使用
- DataReader:只读、只进的结果集,一条一条读取数据(StreamReader、XmlReader微软的类库中这些Reader的使用方式都差不多),不能修改,不能后退,常用方法
Reader()
和索引器 - DataAdapter:一个封装了上面三个对象的对象
封装SqlHelper
先写好App.config配置文件
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<connectionStrings>
<add name="连接名" connectionString="连接字符串"/>
</connectionStrings>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
</startup>
</configuration>
对SqlCommand中的方法进行封装,函数名和返回值相同
public static class SqlHelper
{
//定义一个连接字符串,从App.config文件读取
//需要 System.Configuration.ConfigurationManager
private static readonly string ConStr =
ConfigurationManager.ConnectionStrings["连接名"].ConnectionString;
/// <summary>
/// 执行增删改操作
/// </summary>
/// <param name="sql">sql语句</param>
/// <param name="pms">参数</param>
/// <returns></returns>
public static int ExcuteNonQuery(string sql, params SqlParameter[] pms)
{
using (SqlConnection con = new SqlConnection(ConStr))
{
using (SqlCommand cmd = new SqlCommand(sql, con))
{
//避免pms传入长度为0的数组
if (pms != null)
{
cmd.Parameters.AddRange(pms);
}
con.Open();
return cmd.ExecuteNonQuery();
}
}
}
/// <summary>
/// 执行查询,返回单个值的方法
/// </summary>
/// <param name="sql">SQL语句</param>
/// <param name="pms">参数</param>
/// <returns></returns>
public static object ExecuteScalar(string sql, params SqlParameter[] pms)
{
using (SqlConnection con = new SqlConnection(ConStr))
{
using (SqlCommand cmd = new SqlCommand(sql, con))
{
if (pms != null)
{
cmd.Parameters.AddRange(pms);
}
con.Open();
return cmd.ExecuteScalar();
}
}
}
/// <summary>
/// 执行查询,返回多行多列的方法
/// </summary>
/// <param name="sql">SQL语句</param>
/// <param name="pms">参数</param>
/// <returns></returns>
public static SqlDataReader ExecuteReader(string sql, params SqlParameter[] pms)
{
SqlConnection con = new SqlConnection(ConStr);
using (SqlCommand cmd = new SqlCommand(sql, con))
{
if (pms != null)
{
cmd.Parameters.AddRange(pms);
}
try
{
con.Open();
return cmd.ExecuteReader(System.Data.CommandBehavior.CloseConnection);
}
catch
{
con.Close();
con.Dispose();
throw;
//让外层知道出现异常,抛出全部异常
//throw new Exception();可以写在任何地方,但只抛出自己写的一个异常
}
//返回之前连接对象就关闭了
//使用reader时,连接必须是打开的
//不使用using创建连接对象,会导致reader使用完毕仍不放入连接池
//使用CommandBehavior.CloseConnection时,其它地方使用using调用完reader会关闭连接对象
//System.Data.CommandBehavior.CloseConnection这个枚举参数,表示将来使用完毕SqlDataReader后
//在关闭reader的同时,在SqlDataReader内部会将关联的Connection对象也将关闭掉
//但是连接对象没有使用using,出异常将关闭不了连接,要使用try catch语句关闭连接
}
}
/// <summary>
/// 查询数据库返回DataTable
/// </summary>
/// <param name="sql">SQL语句</param>
/// <param name="pms">参数</param>
/// <returns></returns>
public static DataTable ExecuteDataTable(string sql, params SqlParameter[] pms)
{
DataTable dt = new DataTable();
using (SqlDataAdapter adapter = new SqlDataAdapter(sql, ConStr))
{
if (pms != null)
{
adapter.SelectCommand.Parameters.AddRange(pms);
}
adapter.Fill(dt);
}
return dt;
}
}
封装SqlHelper,包含执行存储过程
上述代码执行存储过程时需要在sql语句中添加exec
以及参数名,可以在方法中添加一个参数简化,也可以重载,使用存储过程时再调用相应的方法
最终完成代码
public static class SqlHelper
{
//定义一个连接字符串,从App.config文件读取
//需要 System.Configuration.ConfigurationManager
private static readonly string ConStr =
ConfigurationManager.ConnectionStrings["连接名"].ConnectionString;
/// <summary>
/// 执行增删改操作
/// </summary>
/// <param name="sql">sql语句</param>
/// <param name="pms">参数</param>
/// <returns></returns>
public static int ExcuteNonQuery(string sql, CommandType cmdType, params SqlParameter[] pms)
{
using (SqlConnection con = new SqlConnection(ConStr))
{
using (SqlCommand cmd = new SqlCommand(sql, con))
{
cmd.CommandType = cmdType;
if (pms != null)
{
cmd.Parameters.AddRange(pms);
}
con.Open();
return cmd.ExecuteNonQuery();
}
}
}
/// <summary>
/// 执行查询,返回单个值的方法
/// </summary>
/// <param name="sql">SQL语句</param>
/// <param name="pms">参数</param>
/// <returns></returns>
public static object ExecuteScalar(string sql, CommandType cmdType, params SqlParameter[] pms)
{
using (SqlConnection con = new SqlConnection(ConStr))
{
using (SqlCommand cmd = new SqlCommand(sql, con))
{
cmd.CommandType = cmdType;
if (pms != null)
{
cmd.Parameters.AddRange(pms);
}
con.Open();
return cmd.ExecuteScalar();
}
}
}
/// <summary>
/// 执行查询,返回多行多列的方法
/// </summary>
/// <param name="sql">SQL语句</param>
/// <param name="pms">参数</param>
/// <returns></returns>
public static SqlDataReader ExecuteReader(string sql, CommandType cmdType, params SqlParameter[] pms)
{
SqlConnection con = new SqlConnection(ConStr);
using (SqlCommand cmd = new SqlCommand(sql, con))
{
cmd.CommandType = cmdType;
if (pms != null)
{
cmd.Parameters.AddRange(pms);
}
try
{
con.Open();
return cmd.ExecuteReader(System.Data.CommandBehavior.CloseConnection);
}
catch
{
con.Close();
con.Dispose();
throw;
}
}
}
/// <summary>
/// 查询数据库返回DataTable
/// </summary>
/// <param name="sql">SQL语句</param>
/// <param name="pms">参数</param>
/// <returns></returns>
public static DataTable ExecuteDataTable(string sql, CommandType cmdType, params SqlParameter[] pms)
{
DataTable dt = new DataTable();
using (SqlDataAdapter adapter = new SqlDataAdapter(sql, ConStr))
{
adapter.SelectCommand.CommandType = cmdType;
if (pms != null)
{
adapter.SelectCommand.Parameters.AddRange(pms);
}
adapter.Fill(dt);
}
return dt;
}
}
使用示例
static void Main(string[] args)
{
string username = "admin";
string password = "123456";
string sql = "select COUNT(*) from Users where Username=@username and Password=@password";
SqlParameter[] pms = new SqlParameter[]
{
new SqlParameter("@username",SqlDbType.NVarChar,10){Value=username},
new SqlParameter("@password",SqlDbType.VarChar,32){Value=password}
};
int count = Convert.ToInt32(SqlHelper.ExecuteScalar(sql, pms));
//int count = Convert.ToInt32(SqlHelper.ExecuteScalar(sql, CommandType.Text, pms));
if (count > 0)
{
Console.WriteLine("登录成功");
}
else
{
Console.WriteLine("用户名或密码错误");
}
}
执行存储过程的话
static void Main(string[] args)
{
string username = "admin";
string password = "123456";
string sql = "存储过程名";
SqlParameter[] pms = new SqlParameter[]
{
new SqlParameter("@username",SqlDbType.NVarChar,10){Value=username},
new SqlParameter("@password",SqlDbType.VarChar,32){Value=password}
};
int count = Convert.ToInt32(SqlHelper.ExecuteScalar(sql, CommandType.StoredProcedure, pms));
if (count > 0)
{
Console.WriteLine("登录成功");
}
else
{
Console.WriteLine("用户名或密码错误");
}
}
注意事项(SqlDataReader)
使用SqlDataReader时必须保证连接是打开状态,当SqlDataReader使用完毕后,必须把SqlDataReader关闭,释放,同时关闭释放连接对象
static void Main(string[] args)
{
string conStr = "";
using (SqlConnection con = new SqlConnection(conStr))
{
string sql = "select * from Users";
using (SqlCommand cmd = new SqlCommand(sql, con))
{
con.Open();
using (SqlDataReader reader = cmd.ExecuteReader())
{
//查询语句在服务器端执行
//执行完毕后,服务器端查询出数据,保存在服务器内存中,并没有返回给应用程序
//只是返回给应用程序一个reader对象,这个对象就是用来获取数据的对象
//通过reader一条一条获取数据
//1、在获取数据之前,先判断本次执行查询后是否查询到数据
if (reader.HasRows)//有数据则为true
{
//2、如果有数据,那么接下来就一条一条获取数据
//reader一次只能取一条数据
//每次获取之前要先调用Read()方法
//bool Read()
//使 SqlDataReader 前进到下一条记录。移动到null上返回false
//如果存在多个行,则为 true;否则为 false。
//移动到下一条数据,上一条自动销毁
while (reader.Read())
{
//获取当前reader指向的数据
//FieldCount 获取查询到的当前行中的列数。
for (int i = 0; i < reader.FieldCount; i++)
{
//GetValue只能通过列索引来获取列的值
//reader[]可以通过列名来获取列的值,如,reader["Id"]
//字符串索引器调用GetOrdinal方法,在给定列名称的情况下获取列序号。
//Console.Write(reader.GetValue(i)+"\t");
Console.Write(reader[i] + "\t");
//遇到数据库中的null值输出空字符串,因为是DBNull.Value,不是C#的null,不报异常
//GetXXX使用强类型读取列中数据
//读取到的数据直接就是对应的类型,不是object类型,使用起来更方便
//reader只能读取数据,不能修改数据
//reader[i] = "";报错
}
Console.WriteLine();
}
//使用reader时必须保证连接是打开状态
//当reader使用完毕后,必须把reader关闭,释放,同时关闭释放连接对象
}
else
{
Console.WriteLine("没有查询到任何数据");
}
}
}
}
}
使用GetXxxx()方法获取数据
static void Main(string[] args)
{
string conStr = "";
using (SqlConnection con = new SqlConnection(conStr))
{
string sql = "select * from Users";
using (SqlCommand cmd = new SqlCommand(sql, con))
{
con.Open();
using (SqlDataReader reader = cmd.ExecuteReader())
{
if (reader.HasRows)
{
while (reader.Read())
{
Console.Write(reader.IsDBNull(0) ? "null" : reader.GetInt32(0) + "\t");
Console.Write(reader.IsDBNull(1) ? "null" : reader.GetString(1) + "\t");
Console.Write(reader.IsDBNull(2) ? "null" : reader.GetBoolean(2) + "\t");
Console.WriteLine();
}
}
}
}
}
}
ADO.NET 封装 SqlHelper 结束
不使用 C# 8.0 的 using 语法确实看着很乱