DataSet
1、 ExecuteNonQuery、Executescalar 都可以封装;ExecuteReader不行,因为封装以后调用SqlDataReader出错。
SqlDataReader是连接相关的,SqlDataReader查询的结果并不是放到程序中,而是放到服务器的数据库中,SqlDataReader相当于一个指针,一旦连接断开就不能再读取了。这样做的好处是无论查询结果有多少行,对程序内存几乎没有影响。
ADO.Net提供了数据集的机制,把查询结果填充到本地内存中,这样连接断开,服务器断开都不影响本地的读取。
DataSetdataset = new DataSet();
SqlDataAdapteradapter = new SqlDataAdapter(cmd);
adapter.Fill(dataset);
SqlDataAdapter是DataSet和数据库沟通的桥梁。数据集DataSet包含若干表DataTable,DataTable包含若干行DataRow。
2、 (1)new SqlParameter(“e”,0)的陷阱
SqlParameter方法有重载,写入参数0会被当作枚举,应改为:new SqlParameter(“e”,(object)0)
(2)sqlconnection在程序中为什么不一直open?
一个数据库可以承载的连接是有限的,对于数据库来说连接是非常宝贵的资源。
3、 DataSet的更新
可以更新行row[“Name”]=”yzk”、删除行datatable.Rows.Remove()、新增行datatable.NewRow()。这一切都是修改内存中的DataSet,没有修改数据库。
可以调用SqlDataAdapter的Update方法将对DataSet的修改提交到数据库,Update方法有很多重载,可以提交整个DataSet、DataTable或者若干DataRow。但需要为SqlDataAdapter提供DeleteCommand、UpdateCommand、InsertCommand它才知道如何将对DataSet的修改提交到数据库,由于这几个Command要求的格式非常苛刻,可以用SqlCommandBuilder自动生成这几个Command,用法很简单:newSqlCommandBuilder(adapter)。
4、 可空数据类型
int? i = null;//可空的int,为解决数据库和C#对于int是否可以为null的不同规定所设置
i.HasValue i.Value
5、弱类型DataSet的缺点
只能通过列名引用,dataset.Tables[0].Rows[0][“Age”],如果写错了列名编译时不会发现错误,因此开发时必须记住列名。
int age =Convert.ToInt32(dataset.Rows[0][“Age”]),取到的字段的值是object类型,必须小心进行类型转换,麻烦,容易出错。
运行时才能知道所有列名,数据绑定麻烦,无法使用WinForm、ASP.Net的快速开发功能。(?)
6、 VS自动生成强类型DataSet
添加→新建→数据集
将表从服务器资源管理器拖放到DataSet中。注意拖放过程是自动根据表结构生成强类型DataSet等类,没有把数据也拖过来,程序还是连的那个数据库,自动将数据库连接字符串写在了App.Config中。
代码中使用DataSet示例:
CC_RecordTableAdapteradapter = new CC_RecordTableAdapter();
如何得知Adapter的类名?选中DataSet中下半部分的Adapter,Name属性就是类名。需要右键点击类名→解析
取得所有的数据:adapter.GetData()
遍历显示所有数据:
i<adapter.GetData().Count;
adapter.GetData()[i].Age;
常见问题:类的内部定义的类要通过包含namespace的全名来引用,不能省略。
7、 更新DataSet
调用Adapter的Update方法就可以将DataSet的改变保存到数据库。adapter.Update(datatable)
要调用Update方法更新必须设置数据库主键,后面的Delete也是如此。
8、 添加新的SQL语句
设计器的Adapter中点右键,选择“添加查询”→“使用SQL语句”,就可以添加多种类型的SQL语句
9、 强类型DataSet的连接原理
通过查看生成的源代码的值,生成的强类型DataAdapter默认每次调用方法都是打开连接、执行、关闭连接,而如果操作之前连接已经打开则不会自动帮我们连接、关闭,因此如果想批量操作提高效率可以操作之前先自己Open。