65.9K
CodeProject 正在变化。 阅读更多。
Home

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

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.82/5 (27投票s)

2004 年 2 月 24 日

5分钟阅读

viewsIcon

338061

downloadIcon

2

本文档旨在提供使用 Microsoft .NET DataTables、DataSets 和 DataGrid 的实用指南

4 DataSet

4.1 DataSet 方法

DataSet 方法

描述

AcceptChanges()

接受对 DataSet 的所有更改

Clear()

从 DataSet 中的所有表中删除所有行,即删除所有数据。

Clone()

创建一个新的 DataSet,其中所有表都具有相同的表结构,包括任何约束和关系。不复制数据。

Copy()

与 DataSet 的 Clone() 相同,但包含所有数据。

GetChanges()

创建一个包含对 DataSet 所做更改的 DataSet。如果调用了 AcceptChanges,则仅返回自上次调用以来所做的更改。

HasChanges()

如果对 DataSet 进行了任何更改(包括添加表和修改行),则返回 true。

WriteXml()

输出一个 XML 文件,其中包含所有表、数据、约束和关系的架构。

ReadXml()

输入一个包含架构、表、数据、约束和关系的 XML 文件。

4.2 DataSet 属性

DataSet 属性

描述

CaseSensitive

如果设置为 true,则 DataSet 表中的字符串比较区分大小写,否则不区分。

DataSetName

DataSet 的名称

HasErrors

如果在 DataSet 中的任何表中存在错误,则返回 true。

Relationss

关系集合

方法/属性

描述

Add()

AddRange()

如果要将两个或多个关系添加到集合中,可以使用此方法添加。它们将按照指定范围中的顺序追加到现有集合中。

CanRemove

如果可以从集合中删除关系,则返回 true。

Clear()

从关系集合中删除所有关系。

Contains()

如果集合包含命名关系,则返回 true。

Count

返回集合中关系的数量。

IndexOf()

返回集合中与名称匹配的关系的索引。

Remove()

通过名称从集合中删除关系。

RemoveAt()

通过索引从集合中删除关系。

表格

表集合

方法/属性

描述

Add()

将表添加到集合中。

AddRange()

如果要将两个或多个表添加到集合中,可以使用此方法添加。它们将按照指定范围中的顺序追加到现有集合中。

Clear()

从集合中删除所有表。

Contains()

如果集合包含一个 TableName 等于 name 的表,则返回 true。

Count

返回集合中表的数量。

IndexOf()

返回集合中 TableName 等于 name 的表的索引。

Remove()

通过 TableName 从集合中删除表。

RemoveAt()

通过索引从集合中删除表。

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);
}

下一篇

Data Grids

© . All rights reserved.