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

使用 XML 和 ADO.NET 创建留言簿

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.91/5 (8投票s)

2002年8月7日

6分钟阅读

viewsIcon

339487

downloadIcon

2215

通过创建留言簿,演示 ADO.NET 处理 XML 的能力。

引言

世界各地的 Web 开发人员已经创建了不同类型的留言簿。假设人们对留言簿的需求永无止境,我想再添加一个。我的目标不是要制作一个完整、可部署的留言簿,而仅仅是为了演示 .NET Framework 通过 ADO.NET 对象处理 XML 文件和 XML Schema 的能力。这个留言簿保持简单直观,因此您可以轻松修改它以满足您的需求或应对更苛刻的任务。

我称之为 XML 留言簿,它非常适合没有数据库访问权限的网站,或者那些不想费太多周折在其网站中提供留言簿的网站管理员。此外,您可以使用像记事本一样简单的应用程序轻松编辑 XML 文件以删除不需要的条目。

我将使用 ADO.NET 对象(DataSetDataTableDataRowDataColumnDataView)来访问和操作 XML 留言簿的 XML 数据。还有其他一些方法可以实现这一点,例如使用 .NET XML 类。但是,目前我个人建议使用 ADO.NET,因为它可以将 XML 数据表示为关系信息,就像您正在处理真实的数据库一样。

定义表结构

XML 留言簿将有一个如下所示的表结构

Column Name    Data Type    Properties
Id             Int32        Primary Key, Auto Increment
Time           DateTime
Author         String
Subject        String
Comments       String

这是我们将在整个脚本中使用的数据结构。使用 ADO.NET,我们可以使用 DataTableDataColumn 对象以编程方式定义表结构。以下语句创建 DataSet 的实例并将其标识为 myDataSet。然后我们从 myDataSet 创建 DataTable 的实例作为新表,将其命名为 guestbook,并将其标识为 myDataTable

Dim myDataSet As DataSet = New DataSet
Dim myDataTable As DataTable = DataSet.Tables.Add("guestbook")

创建新表后,我们可以开始定义列及其属性,如以下代码所示。第一行创建 DataColumn 的实例作为 myTable 的新列,将其命名为 id,数据类型为 Int32 (4 字节整数),并将其标识为 myDataColumn。然后,在 With 块中,我们将自动增量设置为开启,从 1 开始 (incrementseed),并且每次有新条目时增加 1 (incrementstep)。最后三行稍微复杂一些。我们希望使用 myTablePrimaryKey 属性设置其主键。但由于 PrimaryKey 属性只接受 DataColumn 数组,我们首先必须定义一个类型为 DataColumn 的单元素数组,将 myDataColumn 分配为其成员,最后将 PrimaryKey 设置为该数组。这样做的目的是允许您将多个列指定为主键。因此,您可以拥有一个由多个列组成的复合主键。

Dim myDataColumn as DataColumn = myTable.Columns.Add("id", 
    Type.GetType("System.Int32"))

With myDataColumn
    .AutoIncrement = true
    .AutoIncrementSeed = 1
    .AutoIncrementStep = 1
End With

Dim arrPrimaryKey(1) As DataColumn
arrPrimaryKey(0) = myDataColumn
myTable.PrimaryKey = arrPrimaryKey

定义其余列更容易,因为我们不想施加任何约束。我们可以按如下方式编写快捷方式

myTable.Columns.Add("datetime", Type.GetType("System.DateTime"))
myTable.Columns.Add("author", Type.GetType("System.String"))
myTable.Columns.Add("subject", Type.GetType("System.String"))
myTable.Columns.Add("comments", Type.GetType("System.String"))

我们可以使用如下简单语句以编程方式在表中添加新行

myDataTable.Rows.Add(new Object() { 1, DateTime.Now, 
    "Author A", 
    "Subject A", 
    "Comments A"})

这行代码创建了一个 Object 数组,设置值,并将其添加到 myDataTableDataRow 集合中。值的顺序必须与我们之前定义的列的顺序匹配。

还有一种更冗长的方法,我个人更喜欢这种方法以求清晰。

Dim myDataRow As DataRow = myDataTable.Rows.NewRow()
myDataRow("id") = 1
myDataRow("time") = DateTime.Now
myDataRow("author") = "Author A"
myDataRow("subject") = "Subject A"
myDataRow("comments") = "Comments A"
myDataTable.Rows.Add(myDataRow)

将表结构存储为 XML Schema

表结构应该存储起来,这样我们每次使用它时都不需要定义表。表结构可以存储为 XML Schema。简单来说,XML Schema 是一组规则,用于管理 XML 文件中的元素和属性如何编写。XML Schema 可以写在一个单独的文件中,扩展名为 *xsd*,也可以写在它所引用的 XML 文件中。后者称为内联 XML Schema。

幸运的是,DataSet 对象已经具备编写和读取 Schema 的能力,因此我们不需要自己设计。WriteXml 方法将 DataSet 的全部内容写入 XML 文件,并可选地将表结构作为内联 XML Schema 写入。相反,我们通过使用 ReadXml 方法从 XML 文件中将数据读回 DataSet。同样,我们有选择读取或不读取 Schema 的选项,尽管建议读取 Schema(如果存在),以确保在操作期间数据有效性和一致性。在 XML 留言簿的情况下,这种机制确保我们添加到 DataTable 的新数据始终符合之前定义的表结构(即,id 列始终自动递增,并且时间字段始终包含有效的 DateTime 数据类型)。

调用 WriteXmlReadXml 方法的语句如下

DataSet.WriteXml(Server.MapPath("guestbook.xml", XMLWriteMode.WriteSchema))

DataSet.ReadXml(Server.MapPath("guestbook.xml", XMLReadMode.ReadSchema))

每个方法的第二个参数是可选的。如果您不指定,默认值是 Auto,这意味着 .NET Framework 将首先扫描 XML 文件。如果它找到 XML 架构,它将使用它;否则,它将通过一个称为“架构推断”的过程自动创建一个新的。这里没有提到其他一些 XmlWriteModeXmlReadMode 选项。有关完整描述,请查阅 MSDN。

Server.MapPath 用于将虚拟地址(由 IIS 识别)转换为物理地址。在本例中,我们假设 guestbook.xmlaspx 文件位于同一文件夹中,并且该文件夹具有写入权限。

我们之前定义的表结构,存储为 XML 架构时,将如下所示

<?xml version="1.0" standalone="yes"?>
<NewDataSet>
  <xs:schema id="NewDataSet" xmlns=""
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
    <xs:element name="NewDataSet" msdata:IsDataSet="true">
      <xs:complexType>
        <xs:choice maxOccurs="unbounded">
          <xs:element name="guestbook">
            <xs:complexType>
              <xs:sequence>
                <xs:element name="id" msdata:AutoIncrement="true"
                msdata:AutoIncrementSeed="1" type="xs:int" />
                <xs:element name="datetime" type="xs:dateTime"
                minOccurs="0" />
                <xs:element name="author" type="xs:string"
                minOccurs="0" />
                <xs:element name="subject" type="xs:string"
                minOccurs="0" />
                <xs:element name="comments" type="xs:string"
                minOccurs="0" />
              </xs:sequence>
            </xs:complexType>
          </xs:element>
        </xs:choice>
      </xs:complexType>
      <xs:unique name="Constraint1" msdata:PrimaryKey="true">
        <xs:selector xpath=".//guestbook" />
        <xs:field xpath="id" />
      </xs:unique>
    </xs:element>
  </xs:schema>
</NewDataSet>

不要担心生成的 XML Schema 的复杂性。由于 ADO.NET 在后台处理 Schema,您很少需要深入研究它。

显示数据

现在到了有趣的部分。您有多种选择来显示留言簿数据。您可以使用 RepeaterDataListDataGrid,或者创建自己的控件以满足您的设计要求。在这个例子中,我使用 Repeater 控件,因为它比其更受欢迎的姐妹控件 DataGrid 具有更大的灵活性。

要在 Repeater 控件中显示 DataSet 的内容,您必须将 DataSet 对象绑定到 Repeater。以下代码块就是这样做的

Dim myDataView As DataView = myDataSet.Tables(0).DefaultView

myRepeater.DataSource = myDataView
myRepeater.DataBind()

首先,您从当前表创建一个 DataView 对象。由于该表是 DataSet 中的第一个也是唯一的表,因此它在表集合中始终具有索引 0。因此,您可以将其引用为 Tables(0)Tables("guestbook")。然后我们将 RepeaterDataSource 属性设置为 DataView 对象,并调用 DataBind 方法以有效地将数据绑定到 Repeater

留言簿的内容将按升序显示,这意味着较新的消息会稍后显示。如果要反转顺序,请在调用 DataBind 方法之前插入以下语句。

myDataView.Sort = "id DESC"

这将根据 id 列按降序对 DataView 进行排序。请注意该值与 SQL 语句的相似性。

Repeater 控件之后,我放置了一个包含三个文本框(AuthorSubjectComments)的表单,以允许访问者在留言簿上发表他们的想法。同样,这非常简单。您可以重新设计表单以适应您的设计,或者进行验证,以便访问者不会留下空白条目。

结论

由于 ADO.NET 对象和 XML 之间紧密的关系,现在我们可以轻松地将 XML 数据作为关系信息进行操作,就像我们正在处理关系数据库一样。我们可以将我们的关系表存储到 XML 文件中,并在保留其数据结构的同时检索它们。这里提到的编程技术适用于需要简单快速数据存储的小任务,避免了典型 SQL 数据库中的大量开销。

© . All rights reserved.