温故而后知新——对ado.net中常用对象的一些解释
在使用ado.net连接数据库获取数据,一般的步骤是:
1、设置好web.config //用来设置服务器数据库的地址以及登录名密码
2、创建Connection对象 //用来创建访问数据库的连接
3、创建Command对象 //用来发送命令(写sql语句)
4、用DataReader获取数据 //获取数据库数据
5、利用DataSet储存获取到的数据 //容器
6、关闭Connection对象和DataReader/DataAdapter的连接 //为了性能,不关闭可能会报错
(其中3、4两步可以用DataAdapter对象一步代替)
一、设置web.config
打开web.config,直接在根节点加入:
<connectionStrings>
<add name="Try" connectionString="data source=数据库地址;initial catalog=数据库名称;persist security info=True;user id=登录名;password=密码;"/>
</connectionStrings>
变成
<configuration> //根节点 <system.web> <compilation debug="true" targetFramework="4.5.1" /> <httpRuntime targetFramework="4.5.1" /> </system.web> <connectionStrings> <add name="Try" connectionString="data source=数据库地址;initial catalog=数据库名称;persist security info=True;user id=登录名;password=密码;"/> </connectionStrings> </configuration>
这样就添加了一个连接字符串,名字叫做Try
二、Connection对象
现在要通过刚刚添加的连接字符串连接数据库了,获取web.config中的连接字符串后新建Connection对象:
using System.Configuration; using System.Data.SqlClient; string connectionString = ConfigurationManager.ConnectionStrings["Try"].ConnectionString; //取名字为Try的连接字符串 SqlConnection conn = new SqlConnection(connectionString); //用这个连接字符串新建Connection对象
三、Command对象
在使用Command对象之前,必须保证我们的Connection对象已经处于open状态:
conn.Open();
Commond对象的创建,无论用哪种形式,只要保证它与Connection对象的联系以及我们写的sql语句传进去了就行:
SqlCommand cmd = conn.CreateCommand(); //通过之前的Connection对象创建 cmd.CommandText = "select top 10 * from Project"; //写sql语句 //或者下面的直接构造函数的形式 SqlCommand sc = new SqlCommand("select top 10 * from Project", conn);
它有三个常用方法
1.ExecuteNonQuery(); 该方法适用于非查询语句,返回受影响的行数(int)
cmd.CommandText = "update Project set Name='tom' where id=3"; int result = cmd.ExecuteNonQuery(); //返回1,即有一条数据被修改
2.ExecuteScalar(); 该方法返回查询结果的第一行第一列数据(object)
cmd.CommandText = "select count(*) from Project"; int result = int.Parse( cmd.ExecuteScalar() ); //返回Project表的总行数,由于返回类型是object,因此需要转换成int
3.ExecuteReader(); 该方法返回一个DataReader对象,用于获取查询的结果,后面详解
四、DataReader对象和DataAdapter对象
1.DataReader的用法
DataReader可以通过Command的ExecuteReader()方法返回,它的核心方法是Read():
SqlDataReader dr = cmd.ExecuteReader(); while (dr.Read()) //Read方法返回一个bool值,如果有值就返回true并前进到下一行,当整个表读取结束了就返回false { Response.Write(dr.GetInt32(0)); //这里假设表的第一列是int型,GetInt32()方法需要传一个int参数,从0开始的列的索引值 }
这样把查询结果的第一列就读取出来的,它适合快速获取一些信息
读取完之后记得关闭DataReader:
dr.Close();
dr.Dispose();
2.DataAdapter的用法
DataAdapter对象也称之为数据适配器对象,用来填充一个DataSet容器:
DataSet a=new DataSet("ds1"); SqlDataAdapter ada = new SqlDataAdapter("select top 10 * from Project", conn); ada.Fill(a);
注:
在用完后记得要关闭Connection和DataReader/DataAdapter:
ada.Dispose();
dr.Dispose();
conn.Close();
conn.Dispose();
这其实很麻烦,用完了还得关闭,为了图简便,可以使用using语法。
其完整的读取数据并返回DataSet示例如下:
static public DataSet FillDataSet(string sql,params SqlParameter[] paras) { string connectionString = ConfigurationManager.ConnectionStrings["Try"].ConnectionString; //取名字为Try的连接字符串 DataSet ds = new DataSet("ds1"); using (SqlConnection conn = new SqlConnection(connectionString)) { using (SqlDataAdapter ada = new SqlDataAdapter(sql, conn)) { ada.SelectCommand.Parameters.AddRange(paras);//传参 ada.Fill(ds); } } return ds; }
另附上完整的ExecuteNonQuery方法:
static public int ExecuteNonQuery(string sql, params SqlParameter[] paras) { int result = 0; using (SqlConnection conn = new SqlConnection(connectionString)) { conn.Open(); SqlCommand cmd = new SqlCommand(sql, conn); cmd.Parameters.AddRange(paras); //传参 result = cmd.ExecuteNonQuery(); } return result; }
注:加了params的参数表示可以不写,即不需要传null,直接ExecuteNonQuery(string sql) 就行了
2014-12-29新增
近日感觉调用的时候有点麻烦,每次传参都需要new SqlParameter[]{new SqlParameter(){ParameterName = name, Value = val}} ; 于是将整个DBHelper类改写成如下形式:
1 public class DBHelper 2 { 3 static string connectionString = ConfigurationManager.ConnectionStrings["Try"].ConnectionString; 4 static public DataSet FillDataSet(string sql, object paras) 5 { 6 DataSet a = new DataSet(); 7 using (SqlConnection conn = new SqlConnection(connectionString)) 8 { 9 conn.Open(); 10 SqlDataAdapter ada = new SqlDataAdapter(sql, conn); 11 ada.SelectCommand.Parameters.AddRange(GetParas(paras)); 12 ada.Fill(a); 13 } 14 return a; 15 } 16 static public List<T> FillList<T>(string sql, object paras) 17 { 18 DataSet a = new DataSet(); 19 using (SqlConnection conn = new SqlConnection(connectionString)) 20 { 21 conn.Open(); 22 SqlDataAdapter ada = new SqlDataAdapter(sql, conn); 23 ada.SelectCommand.Parameters.AddRange(GetParas(paras)); 24 ada.Fill(a); 25 } 26 return DataSetToList<T>(a, 0).ToList(); 27 } 28 static public int ExecuteNonQuery(string sql, object paras) 29 { 30 int result = 0; 31 using (SqlConnection conn = new SqlConnection(connectionString)) 32 { 33 conn.Open(); 34 SqlCommand cmd = new SqlCommand(sql, conn); 35 cmd.Parameters.AddRange(GetParas(paras)); 36 result = cmd.ExecuteNonQuery(); 37 } 38 return result; 39 } 40 static public object ExecuteScalar(string sql, object paras) 41 { 42 object result = 0; 43 using (SqlConnection conn = new SqlConnection(connectionString)) 44 { 45 conn.Open(); 46 SqlCommand cmd = new SqlCommand(sql, conn); 47 cmd.Parameters.AddRange(GetParas(paras)); 48 result = cmd.ExecuteScalar(); 49 } 50 return result; 51 } 52 53 /// <summary> 54 /// DataSetToList 55 /// </summary> 56 /// <typeparam name="T">转换类型</typeparam> 57 /// <param name="dataSet">数据源</param> 58 /// <param name="tableIndex">需要转换表的索引</param> 59 /// <returns></returns> 60 private static IList<T> DataSetToList<T>(DataSet dataSet, int tableIndex) 61 { 62 //确认参数有效 63 if (dataSet == null || dataSet.Tables.Count <= 0 || tableIndex < 0) 64 return null; 65 66 DataTable dt = dataSet.Tables[tableIndex]; 67 68 IList<T> list = new List<T>(); 69 70 for (int i = 0; i < dt.Rows.Count; i++) 71 { 72 //创建泛型对象 73 T _t = Activator.CreateInstance<T>(); 74 //获取对象所有属性 75 PropertyInfo[] propertyInfo = _t.GetType().GetProperties(); 76 for (int j = 0; j < dt.Columns.Count; j++) 77 { 78 foreach (PropertyInfo info in propertyInfo) 79 { 80 //属性名称和列名相同时赋值 81 if (dt.Columns[j].ColumnName.ToUpper().Equals(info.Name.ToUpper())) 82 { 83 if (dt.Rows[i][j] != DBNull.Value) 84 { 85 info.SetValue(_t, dt.Rows[i][j], null); 86 } 87 else 88 { 89 info.SetValue(_t, null, null); 90 } 91 break; 92 } 93 } 94 } 95 list.Add(_t); 96 } 97 return list; 98 } 99 private static SqlParameter[] GetParas(object paras) 100 { 101 if (paras != null) 102 { 103 List<SqlParameter> list = new List<SqlParameter>(); 104 Type t = paras.GetType(); 105 foreach (PropertyInfo pi in t.GetProperties()) 106 { 107 108 string name = pi.Name; 109 object val = pi.GetValue(paras, null); 110 list.Add(new SqlParameter() { ParameterName = name, Value = val }); 111 } 112 return list.ToArray(); 113 } 114 else 115 { 116 return new SqlParameter[0]; 117 } 118 } 119 }
调用的时候就不必再new一个SqlParameterp[]数组了,可以直接
int id = 20 , fid = 3; string sql = "select * from tb where id=@userID and uId=@uId"; DataSet ds = DBHelper.FillDataSet(sql,new { userID = id , uId=fid });
传参就简单多了。缺陷是无法使用params关键字了,params关键字只能修饰一维数组。所以没有参数的时候也记得写个null,例:
string sql = "select * from tb"; DataSet ds = DBHelper.FillDataSet(sql,null);
2016-11-17新增
增加对事务的支持,整个类代码如下:
1 public class DbHelper 2 { 3 #region 静态 4 private static string ConnStr { get; set; }//静态类的连接字符串,后面的实例统一调用这个连接字符串 5 /// <summary> 6 /// 设置连接字符串 7 /// </summary> 8 /// <param name="connStr"></param> 9 public static void SetConnectionString(string connStr) 10 { 11 DbHelper.ConnStr = connStr; 12 } 13 /// <summary> 14 /// 将object转换成SqlParameter[] 15 /// </summary> 16 /// <param name="paras"></param> 17 /// <returns></returns> 18 private static SqlParameter[] ConvertToSqlParameter(object paras) 19 { 20 List<SqlParameter> list = new List<SqlParameter>(); 21 if (paras != null) 22 { 23 Type t = paras.GetType(); 24 foreach (PropertyInfo pi in t.GetProperties()) 25 { 26 27 string name = pi.Name; 28 object val = pi.GetValue(paras, null); 29 list.Add(new SqlParameter() { ParameterName = name, Value = val }); 30 } 31 } 32 return list.ToArray(); 33 } 34 #endregion 35 36 //*****************非静态******************* 37 38 #region 基本属性 39 private SqlConnection _conn; 40 protected SqlConnection conn 41 { 42 get 43 { 44 if (_conn == null) 45 { 46 _conn = new SqlConnection(); 47 } 48 return _conn; 49 } 50 } 51 private SqlCommand _cmd; 52 protected SqlCommand cmd 53 { 54 get 55 { 56 if (_cmd == null) 57 { 58 _cmd = new SqlCommand(); 59 _cmd.Connection = conn;//设置cmd对象的conn 60 } 61 return _cmd; 62 } 63 } 64 private SqlDataAdapter _adapter; 65 protected SqlDataAdapter adapter 66 { 67 get 68 { 69 if (_adapter == null) 70 { 71 _adapter = new SqlDataAdapter(); 72 } 73 return _adapter; 74 } 75 } 76 protected SqlTransaction trans { get; set; } 77 private bool IsTrans { get; set; }//是否事务 78 #endregion 79 80 #region 构造函数 81 public DbHelper() 82 { 83 84 } 85 #endregion 86 87 #region 打开或关闭连接对象 88 /// <summary> 89 /// 打开连接,如果已经打开则什么都不执行了 90 /// </summary> 91 private void OpenConnection() 92 { 93 if (this.conn.State != ConnectionState.Open) 94 { 95 this.conn.ConnectionString = DbHelper.ConnStr; 96 this.conn.Open(); 97 } 98 } 99 /// <summary> 100 /// 关闭连接,如果没有开始事务或连接打开时才关闭 101 /// </summary> 102 private void CloseConnect() 103 { 104 if (!this.IsTrans) 105 { 106 if (this.conn.State == ConnectionState.Open) 107 { 108 this.conn.Close(); 109 this.conn.Dispose(); 110 } 111 } 112 } 113 /// <summary> 114 /// 给当前DbCommand对象赋值,并且OpenConnection(); 115 /// </summary> 116 private void OpenConnectAndSetCommand(string sqlText, CommandType cmdType, object param) 117 { 118 OpenConnection(); 119 this.cmd.Parameters.Clear(); 120 if (param != null) 121 { 122 this.cmd.Parameters.AddRange(DbHelper.ConvertToSqlParameter(param)); 123 } 124 this.cmd.CommandText = sqlText; 125 this.cmd.CommandType = cmdType; 126 } 127 #endregion 128 129 #region 执行sql的基本方法 130 /// <summary> 131 /// 执行查询,并返回查询结果的第一行第一列 132 /// </summary> 133 /// <param name="sqlText"></param> 134 /// <param name="cmdType"></param> 135 /// <param name="param"></param> 136 /// <returns></returns> 137 public object ExecuteScalar(string sqlText, object param = null, CommandType cmdType = CommandType.Text) 138 { 139 try 140 { 141 OpenConnectAndSetCommand(sqlText, cmdType, param); 142 return this.cmd.ExecuteScalar(); 143 144 } 145 catch (Exception ex) 146 { 147 throw ex; 148 } 149 finally 150 { 151 CloseConnect(); 152 } 153 } 154 public object ExecuteScalar(string sqlText, CommandType cmdType) 155 { 156 return ExecuteScalar(sqlText, null, cmdType); 157 } 158 159 /// <summary> 160 /// 执行非查询语句,并返回受影响的行数 161 /// </summary> 162 /// <param name="sqlText"></param> 163 /// <param name="cmdType"></param> 164 /// <param name="param"></param> 165 /// <returns></returns> 166 public int ExecuteNonQuery(string sqlText, object param = null, CommandType cmdType = CommandType.Text) 167 { 168 try 169 { 170 OpenConnectAndSetCommand(sqlText, cmdType, param); 171 return this.cmd.ExecuteNonQuery(); 172 173 } 174 catch (Exception ex) 175 { 176 throw ex; 177 } 178 finally 179 { 180 CloseConnect(); 181 } 182 } 183 public int ExecuteNonQuery(string sqlText, CommandType cmdType) 184 { 185 return ExecuteNonQuery(sqlText, null, cmdType); 186 } 187 /// <summary> 188 /// 返回DataSet 189 /// </summary> 190 /// <param name="sqlText"></param> 191 /// <param name="cmdType"></param> 192 /// <param name="param"></param> 193 /// <returns></returns> 194 public DataSet GetDataSet(string sqlText, object param = null, CommandType cmdType = CommandType.Text) 195 { 196 try 197 { 198 OpenConnectAndSetCommand(sqlText, cmdType, param); 199 adapter.SelectCommand = this.cmd; 200 DataSet ds = new DataSet(); 201 adapter.Fill(ds); 202 return ds; 203 } 204 catch (Exception ex) 205 { 206 throw ex; 207 } 208 finally 209 { 210 CloseConnect(); 211 } 212 } 213 public DataSet GetDataSet(string sqlText, CommandType cmdType) 214 { 215 return GetDataSet(sqlText, null, cmdType); 216 } 217 218 /// <summary> 219 /// 返回DataTable 220 /// </summary> 221 /// <param name="sqlText"></param> 222 /// <param name="cmdType"></param> 223 /// <param name="param"></param> 224 /// <returns></returns> 225 public DataTable GetDataTable(string sqlText, object param = null, CommandType cmdType = CommandType.Text) 226 { 227 try 228 { 229 OpenConnectAndSetCommand(sqlText, cmdType, param); 230 adapter.SelectCommand = this.cmd; 231 DataSet ds = new DataSet(); 232 adapter.Fill(ds); 233 return ds.Tables[0]; 234 } 235 catch (Exception ex) 236 { 237 throw ex; 238 } 239 finally 240 { 241 CloseConnect(); 242 } 243 } 244 public DataTable GetDataTable(string sqlText, CommandType cmdType) 245 { 246 return GetDataTable(sqlText, null, cmdType); 247 } 248 #endregion 249 250 #region 关于事务的方法 251 /// <summary> 252 /// 开始执行事务 253 /// </summary> 254 public void TransBegin() 255 { 256 OpenConnection(); 257 this.IsTrans = true; 258 this.trans = this.conn.BeginTransaction(); 259 cmd.Transaction = this.trans; 260 } 261 /// <summary> 262 /// 事务提交 263 /// </summary> 264 public void TransCommit() 265 { 266 this.trans.Commit(); 267 this.IsTrans = false; 268 CloseConnect(); 269 } 270 /// <summary> 271 /// 事务回滚 272 /// </summary> 273 public void TransRollback() 274 { 275 this.trans.Rollback(); 276 this.IsTrans = false; 277 CloseConnect(); 278 } 279 #endregion 280 281 }
调用方法:
1 string connStr = ConfigurationManager.ConnectionStrings["MyDapper"].ConnectionString; 2 DbHelper.SetConnectionString(connStr);//注册连接字符串 3 4 DbHelper db = new DbHelper(); 5 6 db.TransBegin(); 7 8 string sql="select * from Tcar where id=1"; 9 var result = db.GetDataTable(sql); 10 11 db.TransCommit();