C# .NET DataTable、DataSet 和 DataGrid 实用指南 - 第三部分






4.82/5 (27投票s)
2004 年 2 月 24 日
5分钟阅读

338061

2
本文档旨在提供使用 Microsoft .NET DataTables、DataSets 和 DataGrid 的实用指南
4 DataSet
4.1 DataSet 方法
DataSet 方法 |
描述 |
|
接受对 DataSet 的所有更改 |
|
从 DataSet 中的所有表中删除所有行,即删除所有数据。 |
|
创建一个新的 DataSet,其中所有表都具有相同的表结构,包括任何约束和关系。不复制数据。 |
|
与 DataSet 的 |
|
创建一个包含对 DataSet 所做更改的 DataSet。如果调用了 AcceptChanges,则仅返回自上次调用以来所做的更改。 |
|
如果对 DataSet 进行了任何更改(包括添加表和修改行),则返回 true。 |
|
输出一个 XML 文件,其中包含所有表、数据、约束和关系的架构。 |
|
输入一个包含架构、表、数据、约束和关系的 XML 文件。 |
4.2 DataSet 属性
DataSet 属性 |
描述 | ||||||||||||||||||||
|
如果设置为 true,则 DataSet 表中的字符串比较区分大小写,否则不区分。 | ||||||||||||||||||||
|
DataSet 的名称 | ||||||||||||||||||||
|
如果在 DataSet 中的任何表中存在错误,则返回 true。 | ||||||||||||||||||||
|
关系集合
| ||||||||||||||||||||
|
表集合
|
4.3 加载 DataSet
4.3.1 从表加载
如“表”部分所述创建并填充数据的表,可以使用 Add() 方法添加到 Tables 集合中,或者可以使用 AddRange()
方法一次性添加。
使用 Add() 和 AddRange() 将表 dtElements 和 dtIsotopes 添加到 DataSet ElementDS 的两个等效方法示例。
方法 1 – Tables.Add()
// Add the Elements table to the DataSet
elementDS.Tables.Add(dtElements);
// Add the Isotopes table to the DataSet
elementDS.Tables.Add(dtIsotopes);
方法 2 – Tables.AddRange()
ElementDS.Tables.AddRange(new DataTable()
{dtElements, dtIsotopes});
4.3.2 从数据库加载
DataSet 的表集合还可以填充包含数据库记录集数据的关联表,这些数据被视为绑定数据。
4.3.2.1 方法 1 – SqlDataAdapter
以下代码说明了如何使用 SqlDataAdapter 的 Fill()
方法直接加载或绑定数据库记录集,其中 select 查询字符串用于创建记录集。调用 Fill() 方法后,ds 将在其集合中包含一个表,其列标题与 select 查询字符串中的字段名称匹配,列数据类型将与数据库表元素中指定的匹配。每一行都包含对应于每个字段的数据。
System.Data.SqlClient.SqlConnection sqlConnection1;
System.Data.SqlClient.SqlDataAdapter sqlDataAdapter1;
System.Data.SqlClient.SqlCommand sqlSelectCommand1;
sqlConnection1 = new System.Data.SqlClient.SqlConnection();
sqlDataAdapter1 = new System.Data.SqlClient.SqlDataAdapter();
sqlSelectCommand1 = new System.Data.SqlClient.SqlCommand();
sqlSelectCommand1.CommandText = "SELECT ElementsID, AtomicNbr,”
+ “Symbol, AtomicMass, Element FROM [Elements]";
sqlDataAdapter1.SelectCommand = sqlSelectCommand1;
//
// sqlConnection1
// <replace xxxxx, nnnnn and dbName with appropriate values>
//
sqlConnection1.ConnectionString = “workstation id=xxxxx;packet “
+ “ size=4096;user id=nnnnn; pwd=yyyyy;data “
+ “ source=xxxxx; persist”
+ “ security info=False; initial catalog=dbName”;
sqlSelectCommand1.Connection = sqlConnection1;
DataSet ds = new DataSet();
sqlDataAdapter1.Fill(ds);
4.3.2.2 方法 2 – SqlDataReader
此方法比使用 SqlDataAdapter 的 Fill()
方法复杂,但它允许在填充表行之前对数据进行预处理,并且数据不直接绑定到数据库。在此示例中,为了说明目的,不是通过 SQL 查询将数据库记录集限制为包含不同的原子序数行,而是以编程方式完成。
string SQL= "SELECT ElementsID, AtomicNbr, " +
"Symbol, AtomicMass, Element”
+ “ FROM [Elements] order by AtomicNbr ASC";
sqlConnection sqlConnection1=
new sqlConnection (
"connection info to MSDE or SQL Server 2000+”;);
sqlCommand sqlCommand = new sqlCommand (SQL,sqlConnection1);
sqlConnection1.Open();
sqlDataReader elementReader = SqlCommand.ExecuteReader();
// Starting with the element table dt defined in
// the Tables section, an ElementID column
// is added that will be used as the primary key for the row.
DataColumn dc = new DataColumn(“ElementsID”,
System.Type.GetType(“System.Guid”));
dt.Columns.Add(dc);
// Make ‘ElementsID’ a primary key:
dt.PrimaryKey = new DataColumn[]{dt.Columns["ElementsID"]};
// Fill table dt with data from the database table Elements:
注意: SqlDataReader 类有一个方法可以用来确定为特定单元格返回的是 null 值还是不存在的值。例如:
If (!elementReader.IsDBNull(elementReader.GetOrdinal("AtomicNbr")))
{
// fill cell with value
}
else
{
// handle this condition
// for example fill cell with a default value
}
为简洁起见,以下代码中省略了此检查,但使用它是一种好习惯。
DataRow dr;
int PrevAtomicNbr = 0;
try
{
while(myReader.Read())
{
if (PrevAtomicNbr != elementReader.GetInt32(
elementReader.GetOrdinal("AtomicNbr")))
{
PrevAtomicNbr = elementReader.GetInt32(
elementReader.GetOrdinal("AtomicNbr"));
dr = dt.NewRow();
dr[“ElementsID”] =
elementReader.GetGuid(elementReader.GetOrdinal("ElementsID"));
dr[“AtomicNbr”] = elementReader.GetInt32(
elementReader.GetOrdinal("AtomicNbr"));
dr[“Symbol”] = elementReader.GetString(
elementReader.GetOrdinal("Symbol));
dr[“Element”] = elementReader.GetString(
elementReader.GetOrdinal("Element"));
dr[“AtomicMass”] =
elementReader.GetDecimal(elementReader.GetOrdinal("AtomicMass"));
dt.Rows.Add(dr);
}
}
}
finally
{
elementReader.Close();
sqlConnection1.Close();
}
dt.AcceptChanges();
// Add table dt to a new dataset ds and its tables collection
DataSet ds = new DataSet();
ds.Tables.Add(dt);
4.4 关联表
此示例演示了如何通过主键将两个表关联起来。在此示例中,创建了一个 TableName 为 Elements 的表,其主键为“Atomic Number”。第二个 TableName 为 Isotopes 的表通过关系链接,将其 Atomic Number 列与 Elements 主键关联。
// create a new DataSet named Periodic that will
// hold two linked tables with
// TableNames of Elements and Isotopes respectively.
DataSet elementDS = new DataSet("Periodic");
// Create Elements Table
DataTable dtElements = new DataTable("Elements");
dtElements.Columns.Add("Atomic Number", typeof(int));
dtElements.Columns.Add("Element", typeof(string));
dtElements.Columns.Add("Symbol", typeof(string));
// Make ‘Atomic Number’ a primary key in Elements table
dtElements.PrimaryKey = new DataColumn[]
{dtElements.Columns["Atomic Number"]};
// Create Isotopes Table
DataTable dtIsotopes = new DataTable("Isotopes");
dtIsotopes.Columns.Add("Symbol", typeof(string));
dtIsotopes.Columns.Add("Atomic Number", typeof(int));
dtIsotopes.Columns.Add("Isotope Number",typeof(int));
dtIsotopes.Columns.Add("Percent Abundance",
typeof(System.Decimal))
dtIsotopes.Columns.Add("Atomic Mass", typeof(System.Decimal));
// Add tables to the Dataset
ElementDS.Tables.AddRange(new DataTable(){dtElements, dtIsotopes});
DataSet.Relations.Add()
// Add a relationship for Tables Elements and Isotopes
// through the primary key ‘Atomic Number’ in DataSet
// Periodic and name the relationship ‘Isotopes’. This name is
// used in the DataGrid to select table rows, in table Isotopes,
// that contain isotope values for the selected element.
elementDS.Relations.Add("Isotopes",
elementDS.Tables["Elements"].Columns["Atomic Number"],
elementDS.Tables["Isotopes"].Columns["Atomic Number"] );
4.5 DataSet 中的关联表
4.5.1 填充
假设存在另一个 DataSet ds,其 Tables 集合中有一个索引为 0 的表,该表包含 Element 和 Isotope 数据,将用于填充前面部分定义的 elementDS DataSet 表集合中包含的关联表。假设 DataSet ds 中的 Table[0] 具有以下列:
AtomicNbr、Element、Symbol、IsotopeNbr、PctAbundance 和 AtomicMass
其中行按原子序数升序排序,然后按同位素编号升序排序。
// Assign the table containing both Elements and
// Isotopes to dt using index 0
DataTable dt = ds.Tables[0];
// Create two DataTable variables dtElements and dtIsotopes and
// assign tables contained in the DataSet elementDS Tables
// collection using TableNames as indexes.
DataTable dtElements = elementDS.Tables[“Elements”];
DataTable dtIsotopes = elementDS.Tables[“Isotopes”];
DataRow drElement;
DataRow drIsotope;
int prevAtomicNbr = 0;
foreach (DataRow dr in dt.Rows)
{
if(prevAtomicNbr != (int)dr["AtomicNbr"])
{ //need only one row per AtomicNbr in Table[“Elements”]
// Fill an element row with data from dt.
prevAtomicNbr = (int)dr["AtomicNbr"];
drElement = dtElements.NewRow();
drElement["Atomic Number"] = dr["AtomicNbr"];
drElement["Element"] = dr["Element"];
drElement["Symbol"] = dr["Symbol"];
dtElements.Rows.Add(drElement);
}
// Fill an isotope row with data from dt.
drIsotope = dtIsotopes.NewRow();
drIsotope["Isotope Number"] = dr["IsotopeNbr"];
drIsotope["Symbol"] = dr["Symbol"];
drIsotope["Atomic Number"] = dr["AtomicNbr"];
drIsotope["Percent Abundance"] = dr["PctAbundance"];
drIsotope["Atomic Mass"] = dr["AtomicMass"];
dtIsotopes.Rows.Add(drIsotope);
}
4.5.2 删除
要从 DataSet
中删除所有关联表或选定的关联表,首先必须删除所有关系,然后是约束,最后是表,否则会生成关系/约束表错误。
以下代码示例提供了一个通用的例程,用于删除数据集中所有关联的表。
public void RemoveAllTables(DataSet ds)
{
// need to do it in reverse order due to constraints
ds.Relations.Clear();
for (int i=ds.Tables.Count -1; i >=0; i--)
{
ds.Tables[i].Constraints.Clear();
ds.Tables.RemoveAt(i);
}
}
4.6 XML 导出和导入 DataSet 数据
4.6.1 WriteXml
通过指定 DataSet 的属性 Namespace 并使用 WriteXml
方法,可以将 DataSet 中包含的所有表及其架构、关系、约束和数据导出为 XML。
例如
ds.Namespace = "http://www.mydomain.com/xmlfiles”
ds.WriteXml(FileName, XmlWriteMode.WriteSchema);
4.6.2 ReadXml
通过指定 DataSet 的属性 Namespace 并使用 ReadXml
方法,将 XML 文件中包含的所有表及其架构、关系、约束和数据导入到 DataSet 中。一旦进入 DataSet
,它就与其他任何数据集一样。
例如
DataSet ds = new DataSet();
ds.Namespace = "http://www.mydomain.com/xmlfiles";
ds.ReadXml(FileName, XmlReadMode.ReadSchema);
4.7 处理 DataSet 错误
与 DataTable 的 HasErrors
属性类似,DataSet 的 HasErrors
属性会在 DataSet 管理的任何表中发生错误时返回 true。
if(ds.HasErrors)
{ // One or more of the tables in the DataSet has errors.
MessageBox.Show("DataSet has Errors");
// Insert code to resolve errors.
// Refer to ‘Handling DataTable Errors’ section for example of
// handling errors within tables.
}
4.8 使用 DataSet/DataTable 更改更新数据库
以下代码显示了如何创建包含 DataSet 中表的已发生更改的 DataSet。新 DataSet 可用于更新数据库。
// Create temporary DataSet variable.
DataSet dsChanges;
// GetChanges for modified rows only.
dsChanges = ds.GetChanges(DataRowState.Modified);
// Check the DataSet for errors.
if(!dsChanges.HasErrors)
{
// No errors were found, update the DBMS with the SqlDataAdapter da
// used to create the DataSet.
da.RowUpdating += new SqlRowUpdatingEventHandler(OnRowUpdating);
da.RowUpdated += new SqlRowUpdatedEventHandler(OnRowUpdated);
int res = da.Update(dsChanges); // returns the number of rows updated
da.RowUpdating -= new SqlRowUpdatingEventHandler(OnRowUpdating);
da.RowUpdated -= new SqlRowUpdatedEventHandler(OnRowUpdated);
}