上周我们讲到DataTable本周我们接着来介绍ADO.Net的另一个对象DataSet。
简要为大家介绍一下这两者的关系:在我们编写代码的时候从数据库里取出数据,填充到dataset里,再根据表的名字,实例化到 DataTable 中
接下来我为大家详细介绍DataSet
一。思维导图:
二、知识点介绍
DataSet,这是从数据源检索数据的内存中缓存是 ADO.NET 体系结构的主要组件。DataSet包含的集合DataTable对象,可以互相关联起来与DataRelation对象。 此外可以强制实施中的数据完整性DataSet通过使用UniqueConstraint和ForeignKeyConstraint对象。
首先是在ADO.net中的关系:Connection_____Command____DataAdapter____Dataset _____Datareader
● DataSet 是放在内存中的,对DataSet中数据的修改并不直接反应到数据库,要通过 DataAdapter 的 Update 方法更新回数据库
● DataSet相当你用的数据库; DataTable相当于你的表。一个 DataSet 可以包含多个 DataTable
DataSet 由表、关系和约束的集合组成。
下面详细介绍其相关内容:
构造函数:
构造函数
DataSet() |
初始化 DataSet 类的新实例。 |
DataSet(SerializationInfo, StreamingContext) |
初始化具有给定序列化信息和上下文的 DataSet 类的新实例。 |
DataSet(SerializationInfo, StreamingContext, Boolean) |
初始化 DataSet 类的新实例。 |
DataSet(String) |
用给定名称初始化 DataSet 类的新实例。 |
属性
CaseSensitive |
获取或设置一个值,该值指示 DataTable 对象中的字符串比较是否区分大小写。 |
Container |
获取组件的容器。 (Inherited from MarshalByValueComponent) |
DesignMode |
获取指示组件当前是否处于设计模式的值。 (Inherited from MarshalByValueComponent) |
IsInitialized |
获取一个值,该值指示是否已初始化 DataSet。 |
Locale |
获取或设置用于比较表中字符串的区域设置信息。 |
Namespace |
获取或设置 DataSet 的命名空间。 |
Tables |
获取包含在 DataSet 中的表的集合。 |
方法
AcceptChanges() |
提交自加载此 DataSet 或上次调用 AcceptChanges() 以来对其进行的所有更改。 |
Clear() |
通过移除所有表中的所有行来清除任何数据的 DataSet。 |
Clone() |
复制 DataSet 的结构,包括所有 DataTable 架构、关系和约束。 不要复制任何数据。 |
Copy() |
复制该 DataSet 的结构和数据。 |
CreateDataReader() |
为每个 DataTableReader 返回带有一个结果集的 DataTable,顺序与 Tables 集合中表的显示顺序相同。 |
Dispose(Boolean) |
释放由 MarshalByValueComponent 占用的非托管资源,还可以另外再释放托管资源。 (Inherited from MarshalByValueComponent) |
EndInit() |
结束在窗体上使用或由另一个组件使用的 DataSet 的初始化。 初始化发生在运行时。 |
Equals(Object) |
确定指定的对象是否等于当前对象。 (Inherited from Object) |
GetChanges() |
获取 DataSet 的副本,该副本包含自加载以来或自上次调用 AcceptChanges() 以来对该数据集进行的所有更改。 |
Reset() |
清除所有表并从 DataSet 中删除所有关系、外部约束和表。 子类应重写 Reset(),以便将 DataSet 还原到其原始状态。 |
ToString() |
返回包含 Component 的名称的 String(如果有)。 不应重写此方法。 (Inherited from MarshalByValueComponent) |
事件
Disposed |
添加事件处理程序以侦听组件上的 Disposed 事件。 (Inherited from MarshalByValueComponent) |
Initialized |
初始化 DataSet 后发生。 |
MergeFailed |
当目标和源 DataRow 的主键值相同且 EnforceConstraints 设置为真时发生。 |
下面是关于DataSet的使用步骤:
使用Dataset的几个步骤
第1步,创建到数据源的连接:
SQLConnection con =new SQLConnection("server=localhost;uid=sa;pwd=;database=pubs");
第2步,创建DataSetCommand对象,指定一个存储过程的名字或者一个SQL语句,指定数据链路;
SQLDataSetCommand cmd =new SQLDataSetCommand("SELECT * FROM Authors", con);
第3步,创建一个Dataset对象
DataSet ds = new DataSet();
第4步,调用DataSetCommand的FillData方法,为Dataset填充数据。注意:数据链路没有必要是打开的。如果数据链路是关闭状态,FillData函数会打开它,并在FillData之后关闭数据链路。如果数据链路本来就是打开的,在FillData之后,数据链路依然保持打开状态。
int iRowCount = cmd.FillDataSet(ds, "Authors");
第5步,操作数据。由于FillData返回了记录的个数,我们可以构造一个循环,来操纵Dataset中的数据。
for(int i=0; i< iRowCount; i++){
DataRow dr = ds.Tables[0].Rows[i];
Console.WriteLine(dr["au_lname"]);
}
查询:SqlDataReader 适用于大型数据的读取,它是一条一条的读取,读取出来的数据是存放在服务器上
当正在读取数据的时候,突然与服务中断,将无法读取后面的数据
DataSet 适用于小型数据的读取,它是一次将所有数据读取并存放到本机程序的内存当中,占内存
当正在读取数据的时候,突然与服务中断,数据可继续读取
DataSet可存放若干个表(DataTable),每个表有若干个行(DataRow)
更新:row["Name"]="xgao"; 更新行
table.Rows.Remove(); 删除行
table.NewRow(); 新增行
三、案例解析
例子:使用treeview控件与Dataset进行联合使用,实现以下效果
SqlConnection sqlConnection = new SqlConnection(); //声明并实例化SQL连接;
sqlConnection.ConnectionString =
"Server=(local);Database=EduBaseDemo;Integrated Security=sspi"; //在字符串变量中,描述连接字符串所需的服务器地址、数据库名称、集成安全性(即是否使用Windows验证);
SqlCommand sqlCommand = new SqlCommand(); //声明并实例化SQL命令;
sqlCommand.Connection = sqlConnection; //将SQL命令的连接属性指向SQL连接;
sqlCommand.CommandText = //指定SQL命令的命令文本;
"SELECT * FROM tb_Department;" //该命令分别查询所有院系、专业、班级,查询结果将返回多张表;
+ "SELECT * FROM tb_Major;"
+ "SELECT * FROM tb_Class;";
SqlDataAdapter sqlDataAdapter = new SqlDataAdapter(); //声明并实例化SQL数据适配器,同时借助构造函数,将其SelectCommand属性设为先前创建的SQL命令;
sqlDataAdapter.SelectCommand = sqlCommand; //将SQL数据适配器的查询命令属性指向SQL命令;
DataSet dataSet = new DataSet(); //声明并实例化数据集,用于保存查得的多张表;
sqlConnection.Open(); //打开SQL连接;
sqlDataAdapter.Fill(dataSet); //SQL数据适配器读取数据,并填充数据集;
sqlConnection.Close(); //关闭SQL连接;
DataTable departmentTable = dataSet.Tables[0]; //声明院系数据表,对应数据集的表集合中的第1张数据表;
DataTable majorTable = dataSet.Tables[1]; //声明专业数据表,对应数据集的表集合中的第2张数据表;
DataTable classTable = dataSet.Tables[2]; //声明班级数据表,对应数据集的表集合中的第3张数据表;
DataRelation[] dataRelations = //声明数据关系数组;
{
new DataRelation //实例化数据关系,实现院系表、专业表之间的层次关系;
("Department_Major" //数据关系名称;
, departmentTable.Columns["No"] //父表的被参照列为院系表的编号列;
, majorTable.Columns["DepartmentNo"] //子表的参照列为专业表的院系编号列;
, false) //不创建约束(父列上的唯一约束、子列上的外键约束);
, new DataRelation //实例化数据关系,实现专业表、班级表之间的层次关系;
("Major_Class" //数据关系名称;
, majorTable.Columns["No"] //父表的被参照列为专业表的编号列;
, classTable.Columns["MajorNo"] //子表的参照列为班级表的专业编号列;
,false) //不创建约束(父列上的唯一约束、子列上的外键约束);
};
dataSet.Relations.AddRange(dataRelations); //将数据关系数组批量加入数据集的关系集合中;
this.trv_EducationUnit.Nodes.Clear(); //树形视图的节点集合清空;
List<TreeNode> treeNodes = new List<TreeNode>(); //声明并实例化树形节点列表;
foreach (DataRow departmentRow in departmentTable.Rows) //遍历院系数据表中的每一数据行;
{
TreeNode departmentNode = new TreeNode(); //声明并实例化院系节点,该节点对应当前某个院系;
departmentNode.Text = departmentRow["Name"].ToString(); //院系节点的文本设为当前院系的名称;
treeNodes.Add(departmentNode); //院系节点加入树形节点列表,成为第0级节点之一;
foreach (DataRow majorRow in departmentRow.GetChildRows("Department_Major")) //借助先前定义的数据关系,遍历当前院系所在数据行的子行,即下属所有专业;
{
TreeNode majorNode = new TreeNode(); //声明并实例化专业节点,该节点对应当前某个专业;
majorNode.Text = majorRow["Name"].ToString(); //专业节点的文本设为当前专业的名称;
departmentNode.Nodes.Add(majorNode); //专业节点加入当前院系节点的节点集合,成为第1级节点之一;
foreach (DataRow classRow in majorRow.GetChildRows("Major_Class")) //借助先前定义的数据关系,遍历当前专业所在数据行的子行,即下属所有班级;
{
TreeNode classNode = new TreeNode(); //声明并实例化班级节点,该节点对应当前某个班级;
classNode.Text = classRow["Name"].ToString(); //班级节点的文本设为当前班级的名称;
classNode.Tag = classRow["No"]; //班级节点的标签设为当前班级的编号;
majorNode.Nodes.Add(classNode); //班级节点加入当前专业节点的节点集合,成为第2级节点之一;
}
}
}
this.trv_EducationUnit.Nodes.AddRange(treeNodes.ToArray());