Дата публикации статьи: 12.05.2006 09:18

Поиск в XML документе с помощью DataSet и DataView

Автор: Chris Scott
[Оригинал статьи] [Обсудить в форуме]
Перевод с английского: Виталий Готовцов
WWW: http://www.vitgot.narod.ru
Перевод с C#: Гайдар Магдануров

Иногда вам нужны основные возможности базы данных, но не хочется трудностей и возможных издержек разработки базы ради маленького приложения. С помощью объекта .NET DataSet и простого документа XML мы можем эмулировать основные возможности базы данных. В этом примере мы используем XML документ, который содержит информацию о нашем продукте. Мы хотим искать продукт, основываясь на SKU, и получить его цену и описание для веб-страницы.
    Наш список содержит три продукта. Следующий документ является базовым XML документом, productlist.xml, содержащим наши данные:

<?xml version="1.0" encoding="utf-8" ?>
<ProductList>
  <Products>
    <SKU>1</SKU>
    <Price>100.00</Price>
    <Description>Штука #1</Description>
  </Products>
  <Products>
    <SKU>2</SKU>
    <Price>10.00</Price>
    <DescriptionШтука #2</Description>
  </Products>
  <Products>
    <SKU>3</SKU>
    <Price>30.00</Price>
    <Description>Штука #3</Description>
  </Products>
</ProductList>

Если рассматривать этот документ в категориях баз данных, данные внутри тэгов ProductList являются нашей базой данных. Данные внутри тэгов Products являются таблицей в базе данных. SKU, Price и Descriptions – столбцы в таблице Products. Так же, как в базе данных, мы хотим получить строку значений, основанную на значении в столбце.
    Прежде всего, нам необходимо прочитать наш XML-документ в то, что сможет прочитать .NET. Это очень легко сделать с помощью метода ReadXml объекта DataSet. Используя DataSet, мы можем обрабатывать наши данные, как данные в базе данных. Также, сравнивая использование XML-объектов в .NET, результаты DataSet требуют меньше кода и сложностей.
    Все, что нам нужно сделать, это создать новый DataSet и велеть ему прочитать в него наш XML-документ:

Dim dsProducts As New DataSet()
dsProducts.ReadXml(Server.MapPath("productlist.xml"))

    Методу ReadXml передается имя XML-файла, который необходимо прочесть. В этом примере предполагается, что файл называется productlist.xml и он находится в каталоге, который использует веб-страница.
    Теперь, когда наши данные находятся в DataSet, нам нужно сделать к нему запрос об SKU и получить Price и Descriptions соответствующего товара. Чтобы сделать это, мы будем использовать объект DataView:

Dim dvProducts As New DataView(dsProducts.Tables("Products"))
dvProducts.Sort = "SKU"

    DataView создается во время передачи конструктора DataTable, «Products», в наш DataSet. После того, как мы создали DataView, нам необходимо отсортировать ее. Поскольку мы используем SKU в качестве контрольного значения, нам необходимо сортировать по нему. Оно подобно индексу, или первичному ключу, в базе данных. Если мы не проведем сортировку DataView, мы получим ошибку исполнения (runtime error), когда попытаемся использовать метод Find. С помощью сортированного DataView используйте метод Find, чтобы получить только ту строку (или строки), которые соответствуют переданному значению SKU. В этом примере мы хотим вернуть значения Price и Description для продукта, значение SKU которого равны 1:

Dim rowIndex As Integer = dvProducts.Find("1")
Dim Price, Description As String

If rowIndex = - 1 Then
  ' Не найдено искомых данных
  Response.Write("Не найдено")
Else
  Price = dvProducts(rowIndex)("Price").ToString()
  Response.Write(("Цена: " + Price))
  Description = dvProducts(rowIndex)("Description").ToString()
  Response.Write(("Описание: " + Description))
End If

Метод Find объекта DataView возвращает интервал, индекс строки которого в DataView содержит переданное ему ключевое значение. Если соответствия нет, он возвращает -1.
Вот и всё. Для простого использования этот метод хранения и нахождения информации может быть гораздо легче, чем использование базы данных, однако необходимо иметь в виду некоторые моменты.
    Во-первых, наш простой XML-документ содержит все данные в виде текстовых строк. Это не очень большая проблема, поскольку мы можем использовать типы данных .NET, чтобы разбирать структуру наших строковых данных и преобразовывать их в целые числа и даты, но необходимо помнить, что когда вы передаете ключевое значение методу Find, оно должно быть строковым. Второе, если мы хотим получить одну «строку» возвращаемых данных, соответствующих ключевому значению, нам необходимо быть уверенными в том, что в XML-документе не содержится копий ключа – в базе данных мы можем легко обеспечить выполнение этого условия, установив столбец идентифицирующим.
    Если вы используете этот метод в коммерческом ASP.NET приложении, в котором вы используете относительно малое количество данных и вы не часто меняете их, вы можете захотеть поместить объект DataSet в кэш, чтобы не возникало необходимости проводить парсинг XML-документа при каждом запросе. Примените CacheDependency к XML-файлу, чтобы быть уверенным, что кэш недействителен, когда документ изменился.
Загрузите следующий код консольного приложения:

Imports System
Imports System.Data


Namespace productsxml

Class main

Public Overloads Shared Sub Main()
    Main(System.Environment.GetCommandLineArgs())
End Sub

  Sub Main(args() As String)

  Dim dsProducts As New DataSet()
  dsProducts.ReadXml("productlist.xml")

  Dim dvProducts As New DataView(dsProducts.Tables("Products"))
  dvProducts.Sort = "SKU"

  Dim rowIndex As Integer = dvProducts.Find("1")
  Dim Price, Description As String

  If rowIndex = - 1 Then
    Console.WriteLine("Не найдено")
  Else
    Price = dvProducts(rowIndex)("Price").ToString()
    Console.WriteLine(("Цена: " + Price))
    Description = dvProducts(rowIndex)("Description").ToString()
    Console.WriteLine(("Описание: " + Description))
  End If ' Description: Widget #1
  End Sub
End Class
End Namespace