一丶简单的介绍下ADO.NET
了解System.Data命名空间下我们常用的一些类:
1 ①System.Data ?→ DataTable,DataSet,DataRow,DataColumn,DataRelation,Constraint,DataColumnMapping,DataTableMapping 2 ②System.Data.Coummon ????→ 各种数据访问类的基类和接口 3 ③System.Data.SqlClient ??→ 对Sql Server进行操作的数据访问类 4 ??主要有: ??a) SqlConnection ???????????→ 数据库连接器 5 ????????????b) SqlCommand ??????????????→ 数据库命名对象 6 ????????????c) SqlCommandBuilder ???????→ 生存SQL命令 7 ????????????d) SqlDataReader ???????????→ 数据读取器 8 ????????????e) SqlDataAdapter ??????????→ 数据适配器,填充DataSet 9 ????????????f) SqlParameter ????????????→ 为存储过程定义参数10 ????????????g) SqlTransaction ??????????→ 数据库事物
二丶SqlConnection(连接对象)
1.连接字符串
基本语法:数据源(Data Source)+数据库名称(Initial Catalog)+用户名(User ID)+密码(Password)(这种方式比较安全)!
推荐文章 :SQL Server 连接字符串和身份验证,你必须知道的ADO.NET(三) 连接字符串,你小觑了吗?,SQL Server 2008连接字符串写法大全,连接字符串有很多的写法,最保险的写法可以借助“SqlConnectionStringBuilder”类,它提供了全面的连接字符串的属性,以至于减少出错率(相关属性查MSDN),还有大多数连接字符串都写在配置文件里面了!
2.创建连接对象
1 SqlConnectionStringBuilder connectionStringBuilder = new SqlConnectionStringBuilder()2 ?{3 ?????DataSource = "",4 ?????InitialCatalog = "",5 ?????UserID = "",6 ?????Password = ""7 ?};8 SqlConnection connection = new SqlConnection(connectionStringBuilder.ToString());
3.打开和关闭连接对象(使用Using来关闭连接)
1 using(SqlConnection connection = new SqlConnection(connectionStringBuilder.ToString()))2 {3 ????connection.Open();4 ????connection.Close();5 }
关于连接池的文章:你必须知道的ADO.NET(五) 细说数据库连接池(写的还真不赖啊),顶...
三丶SqlCommand(命令对象)
1.实例化的时候默认初始化的四个属性
2.创建命令对象
使用连接对象的“CreateCommand()”方法创建命令对象,也可以使用new来实例化对象!
1 SqlCommand command = connection.CreateCommand(); //这种方式比较好,也可以自己实例化一个对象!
3.几个重要属性
①CommandText:获取或设置要对数据源执行的 Transact-SQL 语句、表名或存储过程!
②CommandType:设置你执行的SQL语句是存储过程还是T-SQL(是一个枚举)!
③Parameters:设置你T-SQL中你需要用到的参数(后面会讲到),是一个“SqlParametersCollection”类型,这个属性很重要,是你通过代码给SQL语句传递参数的途径,所以记住语法,记住一些使用规则讲对编码有很大的帮助!
4.几个重要的方法(相信大家熟悉的不能再熟悉了)
①ExecuteNonQuery:返回是影响的行数(int),主要执行更新,添加,删除等操作!
②ExecuteReader:执行SQL或存储过程,返回的是SqlDataReader类型,主要用来查询!
★ 这边注意这个方法的重载 CommandBehaviour 枚举,成员如下:
1 command.ExecuteReader(CommandBehavior.CloseConnection); //在执行读取之后会自动关闭连接对象
③ExecuteScalar:返回执行结果集中的第一行第一列,如果没有数据,则返回NULL!
Note:因为可能会返回“Null”值,所以需要对结果进行判断,如下:
??object my = cmd.ExecuteScalar(); ????????????????if (object.Equals(my,null)) ?//可以使用Equals进行Null值的判断,易读性强 ????????????????????Console.WriteLine("Not Data"); ????????????????else ????????????????????Console.WriteLine("Yes");
④CreateParameter:创建SqlParameter实例
1 SqlParameter para = cmd.CreateParameter() //此方法适合SQL语句中只有一个参数的情况!
推荐文章:你必须知道的ADO.NET(六) 谈谈Command对象与数据检索
你必须知道的ADO.NET(七) Wow!Command对象高级应用
四丶SqlParameter(Sql参数)
1.几个重要的属性
ParameterName: 设置参数名
Value: 给参数设置值
Size: 设置参数字节最大大小(以字节为但为)
SqlDbType: 参数在SQL中的类型
2.命令对象添加参数集合的几种方法
①AddWithValue
②Add
③AddRange
推荐文章:SqlParameter的作用与用法,代码如下:
1 ?using (SqlConnection connection = new SqlConnection("")) 2 ?{ 3 ?????SqlCommand command = connection.CreateCommand(); 4 ?????command.CommandText = ""; 5 ?6 ?????//可以使用这种方式添加多个参数,不过方式不够好 7 ?????command.Parameters.Add("@name", SqlDbType.NVarChar).Value = "yang"; //第一种方式 8 ?????command.Parameters.Add("@age", SqlDbType.Int).Value = 888; 9 ?????command.Parameters.Add("@address", SqlDbType.NVarChar, 100).Value = "Jiang Su";10 11 ?????//这种方式直接给定参数名和参数就可以了,可操作性比较差12 ?????command.Parameters.AddWithValue("@name", "yang");13 ?????command.Parameters.AddWithValue("@age", 888).SqlDbType = SqlDbType.Int;14 ?????command.Parameters.AddWithValue("@address", "Jiang su").SqlDbType = SqlDbType.NVarChar;15 16 ?????//直接使用参数集合添加你需要的参数,推荐这种写法17 ?????SqlParameter[] parameters = new SqlParameter[]18 ?????{19 ?????????new SqlParameter("@name",SqlDbType.NVarChar,100){Value = "yang"},20 ?????????new SqlParameter("@age",SqlDbType.Int,2){Value = 888},21 ?????????new SqlParameter("@address",SqlDbType.NVarChar,20){Value = "Jiang Su"}, 22 ?????};23 ?????command.Parameters.AddRange(parameters); ?//参数也可以是一个Array数组,如果采用数组参数代码的可读性和扩展性就不是那么好了24 25 ?????//当我们把参数都添加好之后,会生成一个“SqlParameterCollection”集合类型,相当于参数的集合26 ?????//那么我们就可以对这些参数进行修改和移除了27 ?????//说穿了“SqlParameterCollection”内部其实是一个List<SqlParameter>的集合,只是它里面的复杂度比较高,考虑的很全面28 ?????command.Parameters[0].Value = "hot girl";29 ?????command.Parameters[0].Size = 200;30 ?}
上面添加的“SqlParameter”参数都被添加到了“SqlParameterCollection”集合中去了,所以我们才能够对它进行读取和修改!
4.定义适当的参数属性获取存储过程的返回值(return) → Direction = ParameterDirection.Output
代码如下:
五丶SqlDataReader(数据流读取器)
说实话,如果单单知道怎么使用读取器,那是非常好学的,如果深入了解,它里面的知识将会非常的吸引人,那么就以我小菜的经验来说说把,各位不要见怪啊!
1.基本用法
2.常用方法
①GetOrdinal:获取指定列名的列序号(索引号),使用这个方法可以把经常变动的列进行固定
1 int name = dr.GetOrdinal("name"); //通过列名来获取当前列的索引号,这样如果下次你列名顺序发生变化也没有关系
②GetName: 获取列名,参数为指定列名的序列号,返回string
1 string columnName = dr.GetName(name); //通过列名所处的索引号来获取列名名称
③IsDBNull:判断当前读取的数据是否为Null,返回类型为Bool
1 ??dr.IsDBNull(coContactID) ? "NULL" : dr.GetInt32(coContactID).ToString() //相信大家都会使用的
④NextResult:当查询为批处理查询时,使用这个方法去读取下一个结果集,返回值为Bool,如果存在多个结果集,则为 true;否则为 false
1 //select * from Employee;select * from County,这样的话就可以采用这种方式2 dr.NextResult(); //记住这个要放在while(dr.Read())之后,因为读取一个数据集之后才能读取下一个数据集
⑤Read:读取数据
读取数据最重要的方法,不说了!
3.常用属性
①HasRow:判断是否包含一行或多行,也就是判断有没有数据,返回类型为Bool
②FieldCount:获取读取的列数,返回类型为Int
③IsClosed:判断读取的数据流是否关闭
所以灵活运用上面的属性讲增强代码的可读性和健壮性,综合示例:
Note:当 SqlDataReader 关闭后,只能调用 IsClosed 和 RecordsAffected 属性,如果调用其它方法或属性将会报错!
4.性能深入剖析
读取数据的时候会有很多种写法,如dr[0].ToString(),dr["Name"].ToString(),dr.GetString(0),dr.GetSqlString(0)等等的读取方式的写法,如果大家去网上查资料就会很容易发现这几种写法存在着一些差异!
下面是读取数据性能的总结:
1 ????SqlDataReader读取方法:2 ????1. DataReader ????索引 ??+ 基于 [序列号] → dr[0].ToString ???????| Index-based access3 ????2. DataReader ????索引 ??+ 基于 [列名] ?→ dr["Name"].ToString ????| 性能最差4 ????3. Get ???????????开头的 + 基于 [序列号] → dr.GetString(0) ?????| type-access5 ????4. GetSql ????????开头的 + 基于 [序列号] → dr.GetSqlString(0) ??| Provider-specific typed accessor6 ????5. GetOrdinal() ??通过列名获取这个列的序列号 ?????????????????????| 这个方法在提高性能上面有作用7 ????6. 性能(4) --> (3) --> (1) --> (2)
Note:所以在对数据进行读取时要有针对的使用一些性能高的方法,也不是说要追求性能,只是这是一种习惯,对于大多数读取数据库的方法使用索引来读取无疑是最快,记住一句话,“当性能没有成为问题的时候,不要过度的去优化它”,高效而又优美的使用这些方法,才是王道!
推荐文章:SqlDataReader 提前终止的性能问题
PS:我这里的总结其实是以前在园子看到一个人写的,找了半个小时都没找到,如果有人看到过,发个链接给我,我补上!
5.SqlDataReader和DataSet的讨论
推荐文章:谈谈Asp.net网站优化一:SqlDataReader和DataSet的选择
六丶SqlTransaction(事务)
1.代码中的事务
现在代码中基本使用存储过程来控制事务的处理,通过代码进行控制事务也是我们学习ADO.NET的任务之一!
事务是在连接对象之后创建,并把它跟命令对象进行关联,使用try.....Catch捕获异常,然后调用RollBack方法回滚事务!
Commit:提交
RollBack:回滚
2.事务中的命名存储点
一旦你定义了命名存储点,只能回滚命名存储点之后的操作,这是要是情况而使用!
这种情况是当你调用RollBack方法并重载一个命名存储点的参数,如下代码所示:
1 ????using (SqlConnection conn = new SqlConnection(str)) 2 ????{ 3 ?????????conn.Open(); 4 ?????????SqlTransaction transaction = conn.BeginTransaction(); 5 ?????????SqlCommand cmd = conn.CreateCommand(); 6 ?????????cmd.CommandText = ""; 7 ?????????cmd.Transaction = transaction; 8 ?????????//使用命名存储点 9 ?????????transaction.Save("this is point"); ?//定义命名存储点,使用Save方法先保存存储点,定义回滚数据的开始位置10 ????????????????11 ?????????//这边是你要回滚的操作代码,TO DO...12 13 ?????????//把从命名存储点到这里的操作进行回滚14 ?????????transaction.Rollback("this is point"); ?//回滚命名存储点 ?????????????15 ?????}
3.SQL语句中的事务(SQL Server中的事务其实很复杂的)
1 BEGIN TRANSACTION2 3 ????--你需要执行的更新,删除,插入的语句4 ????5 IF(@@ERROR > 0) //这是系统变量,存储你在执行更新,删除,插入操作时发生错误的记录编号6 ????ROLLBACK7 ELSE8 ????COMMIT
推荐文章:浅谈SQL SERVER中事务的ACID
深入sql server中的事务
4.说说“TransactionScope”,让事务更加的简单
1 using (TransactionScope transactionScope = new TransactionScope()) 2 { 3 ????try 4 ????{ 5 ????????using (SqlConnection connection = new SqlConnection()) 6 ????????{ 7 ????????????// TO DO 8 ????????????//提交事务,如果有异常,他会自动回滚的 9 ????????????transactionScope.Complete();10 ????????}11 ????}12 ????catch (Exception)13 ????{14 ????????//捕获异常15 ????????throw;16 ????}17 }
推荐文章:C#综合揭秘——细说事务
七丶SqlDataAdapter(数据适配器)
1.构造函数
1 四个重载: ???2 ??1. 无参3 ??2. SqlDataAdapter(SqlCommand) ?→ 执行命令对象实例4 ??3. SqlDataAdapter(String, SqlConnection) → ①只能指定查询语句 ②连接对象实例5 ??4. SqlDataAdapter(String, ConnectionString) → 用 SelectCommand 和一个连接字符串初始化 SqlDataAdapter 类的一个新实例6 ??Note:第四个重载就把连接对象和命令对象都包含进去了!
2.填充数据(Fill)
最简单的填充数据
1 DataSet dataSet = new DataSet();2 using (SqlConnection conn = new SqlConnection(""))3 {4 ????conn.Open();5 ????SqlCommand command = conn.CreateCommand();6 ????command.CommandText = "select name,age,address from MyInformation";7 ????SqlDataAdapter dataAdapter = new SqlDataAdapter(command);8 ????dataAdapter.Fill(dataSet); ?//填充数据9 }
3.使用“SqlCommandBuilder”对数据进行增删改查
①添加数据
1 ?using (SqlConnection conn = new SqlConnection(ConnectionString())) 2 ?{ 3 ?????conn.Open(); 4 ?????//构建查询语句,也可以指定SqlCommand,其中变换的方法有很多 5 ?????SqlDataAdapter da = new SqlDataAdapter("select LastName,FirstName from dbo.Employees", conn); 6 ?????DataSet ds = new DataSet(); 7 ?????da.Fill(ds); 8 ?????//这句话很重要,它会把你在DataSet增加的数据转化为SQL语句用来更新数据库 9 ?????SqlCommandBuilder cmdBuilder = new SqlCommandBuilder(da);10 ?????//添加行,实例化一个行对象,注意是用NewRow来创建行11 ?????DataRow row = ds.Tables[0].NewRow();12 ?????row[0] = "Yang";13 ?????row[1] = "鬼头";14 ?????ds.Tables[0].Rows.Add(row); ?//添加到表中15 ?????da.Update(ds); ????????????//把DataSet中表和数据库进行对比,更新16 ?}
②修改数据
1 using (SqlConnection conn = new SqlConnection("")) 2 { 3 ????SqlDataAdapter da = new SqlDataAdapter("SQL语句或你自己定义的命令对象", conn); 4 ????DataSet ds = new DataSet(); 5 ????da.Fill(ds); 6 ????//很重要的一句话 7 ????SqlCommandBuilder cmdBuilder = new SqlCommandBuilder(da); 8 ????ds.Tables[0].Rows[12][1] = ""; //修改数据 9 ????da.Update(ds);10 ????//调用Update方法其中隐式的调用了AcceptChanges方法,更新数据集中的数据11 ????//如果你继续使用这个数据集而没有调用这个方法,在后面的使用会出现异常12 ????ds.AcceptChanges(); ?//这句话可以不写的13 }
③删除数据
2 ?{ 3 ?????SqlDataAdapter da = new SqlDataAdapter("SQL语句或你自己定义的命令对象", conn); 4 ?????DataSet ds = new DataSet(); 5 ?????da.Fill(ds); 6 ?????SqlCommandBuilder cmdBuilder = new SqlCommandBuilder(da); 7 ?????//删除数据 8 ?????ds.Tables[0].Rows[12].Delete(); 9 ?????da.Update(ds); ?//这边会隐式调用DataTable的AcceptChanges方法10 ?}
Note(很重要的注意点):值得注意的是Update方法已经隐式帮我调用了AcceptChanges,不比担心状态为改变删除数据会报错,微软已经帮我们都做好了,其实背后就是做的Table.AcceptChanges()这件事,如果在一般的DataTable中会怎么样,提交自上次调用 AcceptChanges 以来对该行进行的所有更改,在调用这个方法之后,表中所有更改将会提交,所有行状态(RowState)状态都将变为Unchanged,在DataSet中我将会说到这些内容!
4.关于“SqlDataAdapter”中Fill方法的一些讨论
简单的写一下,MSDN上都有的,查一下就知道了!
1 ★指定填充数据的数量,如:2 //从第五行到第十行数据填充DataSet ??3 //上面的定义错了4 //应该是从第六行开始,后面的十条记录5 da.Fill(ds,5,10,”MyTable”)
八丶DataSet,DataTable,DataRow,DataColumn
表示数据存放在缓存中,DataSet里面可以包含多个DataTable,DataTable中有多个DataColumn和多个DataRow,包括对各种对DataTable的操作,以及对列和行的操作,在进行DataSet,DataTable进行操作的时候,应该先判断它们是否为Null,这是最基本的!
1.DataTable,DataRow,DataColumn
①创建自己的DataTable
②使用对象集合初始化器简化代码,以及使用“DataColumnCollection”和“DataRowCollection”来操作已添加的行和列
构造函数的访问修饰符为Internal,通过这两个集合可以对Column和Row进行“增,删,改,查”,详细见MSDN,如Remove,Add,RemoveAt etc!
1 dt.Columns.Add(new DataColumn("Age", typeof(Int32))); 2 dt.Columns.Add(new DataColumn() 3 { 4 ????ColumnName = "Address", 5 ????DataType = typeof(string), 6 ????DefaultValue = "江苏海安" 7 }); 8 //我们这边使用Add的方法的第二个重载 9 dt.Rows.Add(new object[] {"11", 44, "222", "yang cao gui"});10 //我们也可以对添加好的行和列进行读取和修改11 dt.Columns[0].ColumnName = "wang wei";12 dt.Rows[0]["wang wei"] = "我把这行这列的值修改了,哈哈";
③使用表达树快速构建自己的列,详细的也可以查MSDN
2.DataRowState(行状态),DataRowVersion(行版本)
①DataRowState(行状态)是“DataRow”中一个很重要的状态,主要有五个方面:
1 ????Added ?????????→ 添加2 ????Deleted ???????→ 删除3 ????Detached ??????→ 分离4 ????Modified ??????→ 修改5 ????Unchanged ?????→ 为改变
Note:如果实例化一个行,但没有加入到任何一个表中,那么它的状态永远是Detached,不存在Add,Modified之分,这个是要注意的!
②DataRowVersion(行版本),有四个版本状态,如下:
1 ????Current ????→ 最近的行,主要针对Deleted操作之前的行,行状态的Deleted2 ????Default ????→ 行的默认状态3 ????Original ???→ 行的原始值 Added,Modified,Unchanged ???4 ????Proposed ???→ 行的建议值
PS:如果想理解它们,应该要写一些示例代码来模拟它们,这样就能很好的熟悉它们了!
强烈推荐这篇文章:→ 深入.NET DataTable(写的很仔细,不错,一定要看的),还有这篇 → 深入.NET DataTable(补遗)。
3.DataSet,DataTable
比较重要的方法:Select,Merge,Copy,Clone,GetChanges等等
关于GetChanges方法:获取数据改变的地方,它所获取的是你上次调用AcceptChanges方法之后修改数据的信息,这点要注意了!
4.下面是对DataSet和DataTable讲的比较好的文章收集
DataTable.Select使用小心得
DataTable 深入解析数据源绑定原理之高级篇
比较两个DataTable数据(结构相同)——5万条数据仅需几秒
5.关于“DataRelation”和“DataView”的知识也很重要
DataView → 表示用于排序、筛选、搜索、编辑和导航的 DataTable的可绑定数据的自定义视图,看文章:DataSet,DataTable,DataView
DataRelation → 表示两个 DataTable 对象之间的父/子关系,看文章:DataRelation(DataSet中父子表)的一个示例
九丶封装数据库操作类(这才是精华)
只有充分理解了上面的知识,才能更好的封装,才能写出健壮的面向对象数据库操作类库,因本人知识有限,简单的封装还可以,但是不足以见人,所以收集了了一些好文章,供我们来学习:
1.SqlHelper- -高悬的双刃剑(到底好用么~~) (提炼更加健壮的代码)
2.我的DbHelper数据操作类(自定义操作类库)
3.JSM SqlHelper 2.0 源码下载(封装的更细啦,有机会研究研究)
4.微软原版SQLHelper类(代码太多,有很多我们会用不到,还有重载的也太多了吧!)
ADO.NET 全面整理
原文地址:https://www.cnblogs.com/YzpJason/p/8459260.html