C# на уроках информатики

Базы данных и XML

Разбить на страницы
Показывать лекцию целиком

Введение в работу с базами данных

Большинство приложений работают с базами данных. Любой программист из крупной компании подтвердит, что роль баз данных в мире вычислительных технологий очень велика. Обладая умением оперировать с базами данных, можно создавать самые разнообразные и действительно полезные приложения.

Возможно, у вас на компьютере уже установлена система управления базами данных, например, Microsoft Access. Лучшая альтернатива – это Microsoft SQL Server Express Edition, с помощью которого вы научитесь работать с базами данных SQL Server, используемыми во многих крупнейших компаниях по всему миру. SQL Server Express включен в пакет установки Visual C# Express, так что, скорее всего, на вашем компьютере он уже установлен.

Для работы с базами данных в библиотеке .NET Framework предусмотрены классы пространства имен System.Data. База данных в корне отличается от таких объектов, как изображения или документы текстовых редакторов, которые часто называют неструктурированными. Информация в базе данных структурирована и обычно хранится в таблицах, а каждая таблица состоит из строк и столбцов.

В программировании строки называют записями, а столбцы задают поля записи. Столбец таблицы определяет тип данных, хранимых в поле записи.

Ниже представлена таблица базы данных, содержащая информацию о планетах. Она имеет следующие столбцы: PlanetName (название планеты), DistanceFromSun (расстояние до Солнца) и Inhabitants (обитатели).

Planet
PlanetName DistanceFromSun (единица измерения – тысяча километров) Inhabitants
Меркурий 57909 Меркуриане
Венера 108200 Венериане
Земля 149600 Земляне
Марс 227940 Марсиане
Юпитер 778400 Юпитериане
Знок 7208100 Знокиане
Сатурн 1423600 Сатурниане
Уран 2867000 Ураниане
Нептун 4488400 Нептуниане
Плутон 5909600 Плутониане

Из таблицы видно, что, например, Венера находится на расстоянии 108 200 тысяч километров от Солнца, а существа, ее населяющие, называются венериане.

Вот еще одна таблица, в которой содержатся сведения о ежегодной численности обитателей разных планет.

Эта совершенно секретная информация, нигде ранее не обнародованная, была получена с инопланетного звездолета, потерпевшего крушение в самой глубине пустыни Гоби. Иметь возможность ознакомиться с ней – большая честь. Очевидно, представители инопланетной цивилизации тоже используют базы данных SQL Server, что и позволило нам привести эти сведения в качестве примера.

Population
PlanetName Year Population
Меркурий 2008 40000
Венера 2008 25
Земля 2008 6000000000
Марс 2008 450000
Юпитер 2008 8326300200
Знок 2008 325000
Сатурн 2008 1000000
Уран 2008 7849345700
Нептун 2008 <NULL>
Плутон 2008 <NULL>
Меркурий 2009 35000
Венера 2009 3
Земля 2009 6500000000
Марс 2009 326800
Юпитер 2009 8451780500
Знок 2009 8700
Сатурн 2009 750000
Уран 2009 8237456000
Нептун 2009 <NULL>
Плутон 2009 <NULL>

Если продолжить разговор о Венере, то, обратите внимание, что в 2008 г. на Венере обитало 25 венериан, а через год, вероятно, в результате извержений вулканов, их осталось всего трое.

Не следует путать базы данных с электронными таблицами. Хотя способ представления данных в электронных таблицах внешне похож на тот, что использовался в приведенных выше примерах, обработка данных происходит в них иначе.

Язык SQL

Существует множество разнообразных систем управления базами данных: Microsoft Access, Oracle, DB2, Microsoft SQL Server, Informix, mySQL, и это далеко не полный список. А нам необходимо обратиться к базе данных из программы на языке C# и "объяснить" ей, что мы ищем.

Проще всего включить в код C# фрагмент на "языке базы данных", с помощью которого выполняется запрос к базе данных на получение нужных столбцов и строк.

(По правде говоря, существует еще и промежуточный уровень – ADO.NET, но сейчас мы не станем заострять на нем внимание.)

Много лет назад специалисты по базам данных договорились об использовании "единого языка баз данных", который понимали бы большинство существующих баз данных. Они назвали его SQL (от англ. Structured Query Language — язык структурированных запросов). Не следует путать язык SQL с системой управления базами данных SQL Server, разработанной корпорацией Microsoft. Язык SQL поддерживают системы управления базами данных (СУБД), выпускаемые самыми разными производителями.

Приступая к разговору о том, как использовать C# при работе с базами данных, сначала познакомимся с основами языка SQL. Ниже приведены примеры операторов на языке SQL и описывается результат их выполнения.

Основными командами SQL являются:

  • SELECT (для выбора некоторых данных);
  • INSERT (для добавления новых данных);
  • UPDATE (для изменения информации, уже существующей в базе данных).
  • Приведем примеры каждой команды.

    Как правило, оператор SELECT записывается следующим образом:

    SELECT <имена извлекаемых столбцов>
    FROM <имена одной или нескольких таблиц базы данных>
    WHERE <условие выбора>

    Рассмотрим пример выбора данных оператором SELECT:

    SELECT * FROM PLANET

    Символ звездочка * означает выбор всех столбцов таблицы. Поэтому данный оператор вернет из базы данных всю таблицу Planet со всеми строками и столбцами.

    Рассмотрим оператор

    SELECT PlanetName, Inhabitants FROM PLANET

    Этот запрос возвращает столбцы PlanetName и Inhabitants со всеми строками из таблицы PLANET.

    PlanetName Inhabitants
    Меркурий Меркуриане
    Венера Венериане
    Земля Земляне
    Марс Марсиане
    Юпитер Юпитериане
    Знок Знокиане
    Сатурн Сатурниане
    Уран Ураниане
    Нептун Нептуниане
    Плутон Плутониане

    Запрос

    SELECT PlanetName, Inhabitants FROM PLANET
    WHERE PlanetName='Венера'

    возвращает столбцы PlanetName и Inhabitants из таблицы PLANET. В результат его выполнения будут включены только те строки, которые содержат значение Венера в столбце PlanetName.

    PlanetName Inhabitants
    Венера Венериане

    Запрос:

    SELECT PlanetName, Population FROM POPULATION
    WHERE Population<100000

    возвращает из таблицы POPULATION строки столбцов PlanetName и Population, для которых значение столбца Population меньше 100000.

    PlanetName Population
    Меркурий 40000
    Венера 25
    Нептун <NULL>
    Плутон <NULL>
    Меркурий 35000
    Венера 3
    Знок 8700
    Нептун <NULL>
    Плутон <NULL>

    Как правило, оператор INSERT записывается следующим образом:

    INSERT INTO <таблица базы данных, к которой добавляются строки>
    (<названия столбцов, в которые будут добавляться значения>)
    VALUES (<значения, которые будут вставлены в указанные столбцы>)

    Пример:

    INSERT INTO PLANET (PlanetName, DistanceFromSun, Inhabitants)
    VALUES (Флафф, 23500000, 'Флаффиане')

    Оператор INSERT добавляет в таблицу PLANET новую строку. Он не возвращает какого-либо результата в программу, но после его выполнения таблица примет вот такой вид:

    PlanetName DistanceFromSun Inhabitants
    Меркурий 57909 Меркуриане
    Венера 108200 Венериане
    Земля 149600 Земляне
    Марс 227940 Марсиане
    Юпитер 778400 Юпитериане
    Знок 7208100 Знокиане
    Сатурн 1423600 Сатурниане
    Уран 2867000 Ураниане
    Нептун 4488400 Нептуниане
    Плутон 5909600 Плутониане
    Флафф 23500000 Флаффиане

    Оператор UPDATE записывается следующим образом:

    UPDATE <таблица базы данных, в которую вносятся изменения>
    SET <названия столбцов, в которые необходимо внести изменения> = <новые значения>
    WHERE <условия>

    Пример:

    UPDATE PLANET SET PlanetName= 'Стафф', Inhabitants='Стаффиане' WHERE PlanetName='Флафф'

    Оператор изменяет некоторые значения в той строке, где столбец PlanetName имеет значение "Флафф". Результат выполнения операции программе не возвращается, но таблица примет вот такой вид:

    PlanetName DistanceFromSun Inhabitants
    Меркурий 57909 Меркуриане
    Венера 108200 Венериане
    Земля 149600 Земляне
    Марс 227940 Марсиане
    Юпитер 778400 Юпитериане
    Знок 7208100 Знокиане
    Сатурн 1423600 Сатурниане
    Уран 2867000 Ураниане
    Нептун 4488400 Нептуниане
    Плутон 5909600 Плутониане
    Стафф 23500000 Стаффиане

    Связи и объединение таблиц базы данных

    Если рассмотреть таблицы внимательно, то можно заметить, что между таблицами PLANET и POPULATION существует связь: и в той и в другой есть столбец с именем PlanetName, который связывает обе таблицы. Благодаря этой связи можно собрать всю информацию об определенной планете.

    Например, можно выбрать из обеих таблиц все строки, касающиеся Венеры:

    PLANET
    PlanetName DistanceFromSun Inhabitants
    Венера 108200 Венериане
    POPULATION
    PlanetName Year Population
    Венера 2008 25
    Венера 2009 3

    А затем объединить полученные данные в одну большую таблицу:

    SELECT *
    FROM PLANET INNER JOIN POPULATION ON PLANET.PlanetName=POPULATION.planetName
    WHERE PlanetName='Венера'
    PLANETS_AND_POPULATION
    PlanetName DistanceFromSun Inhabitants Year Population
    Венера 108200 Венериане 2008 25
    Венера 108200 Венериане 2009 3

    Особенности разных СУБД

    При работе с определенной СУБД необходимо учитывать ее особенности. С этой целью вводится понятие "провайдер данных" – у каждой СУБД он свой. С точки зрения программиста провайдер данных — это набор классов, обеспечивающих связь с базой и осуществляющих доступ к данным. Так, например, за связь с базой данных Microsoft SQL Server отвечает класс SqlConnection, а за связь с базой данных Access — OleDbConnection. Первый является частью провайдера данных SQLDataProvider, второй — провайдера данных OLEDbProvider.

    Программный код меняется в зависимости от того, с какой базой предстоит работать. Для демонстрации возможностей использования баз данных, работающих под управлением различных СУБД, мы создали базу данных Planets в Microsoft SQL Server и в Access. Поскольку формат базы данных в Access 2007 отличается от формата, принятого в предыдущих версиях, реализация выполнена для версий Access 2007 и Access 2003. Естественно, что все особенности построения баз данных находят отражение в программном коде.

    Три варианта базы данных Planets помещены в каталог с именем databases. Файлы Planets.mdf и Planets.ldf, задают базу данных SQL Server, файл Planets.accdb создан для базы данных Access 2007, а Planets.mdb — для базы данных Access 2003.

    В программном коде указывается путь к файлам базы данных, поэтому папка databases должна находиться в том же каталоге, где находится программа, задающая решение, — в нашем случае это файл Examples.sln.

    При работе с базой данных SQL Server программный код зависит от того, с какой версией СУБД приходится работать — с Microsoft SQL Server или Microsoft SQL Server Express Edition.

    В приведенном ниже примере показаны четыре возможных варианта работы:

  • работа с Microsoft SQL Server Express Edition;
  • работа с Microsoft SQL Server;
  • работа с Access 2003;
  • работа с Access 2007.
  • Три варианта закомментированы, а один готов к использованию, в данном тексте это вариант работы с Microsoft SQL Server. В зависимости от того, что установлено на компьютере читателя, следует нужный вариант раскомментировать, а ненужный — закомментировать.

    У большинства пользователей на компьютерах установлен комплект Microsoft Office, возможно, в нем имеется и приложение Access, так что для начала можно поработать с базами данных, подготовленными в этом приложении.

    Когда вам понадобятся более широкие возможности программирования, мы рекомендуем вам установить SQL Server Express. К тому же умение работать с SQL Server гораздо выше ценится в деловой сфере, и чем скорее вы освоите этот инструмент, тем лучше. Загрузить его можно бесплатно с сайта Microsoft: http://www.microsoft.com/.

    Обращение к базам данных из программы, написанной на языке C#

    Далее в трех примерах программ на C# мы будем использовать классы Connection, Command, DataReader, DataAdapter. Префиксы Sql и OleDb указывают на то, с каким вариантом базы данных Planets мы работаем.

    Пример программы 4.1

    Следующая программа подключается к базе данных и посылает ей SQL-запрос. Затем выполняется несколько циклов получения результата запроса, после чего полученные результаты передаются в элемент управления ListBox и отображаются в списке.

    using System.Windows.Forms;
    using System.Data;
    // Пространство имен для работы с базами данных SQL Server
    using System.Data.SqlClient;
    using System.Drawing;
    // Пространство имен для работы с базами данных Access
    using System.Data.OleDb;
    class SimpleDataAccess : Form
    {
      public SimpleDataAccess()
        {
          // Указываем заголовок окна
          this.Text = "Работа с базой данных. Чтение данных.";
          // Добавляем элементы управления - метку и список
          Label labelCaption = new Label();
          labelCaption.Text = "Планеты солнечной системы!";
          labelCaption.Location = new Point(30, 10);
          labelCaption.Width = 200;
          labelCaption.Parent = this;
          
          ListBox listPlanets = new ListBox();
          listPlanets.Location = new Point(30, 50);
          listPlanets.Width = 100;
          listPlanets.Parent = this;
          
          // Формируем запрос к базе данных -
          //запрашиваем информацию о планетах
          string sql = "SELECT * FROM PLANET";
          string connectionString;
          
          /*
          //Вариант 1
          // Подключаемся к базе данных SQL Server Express Edition
          
          // Указываем физический путь к базе данных PLANETS
          string dbLocation =
          ("../../../databases/planets.mdf");
          
          connectionString = @"data source=.\SQLEXPRESS;" +
          "User Instance=true;Integrated Security=SSPI;" +
          "AttachDBFilename=" + dbLocation;
          SqlConnection connection1 = new SqlConnection(connectionString);
          */
          
          //Вариант 2
          // Подключаемся к базе данных SQL Server 2005
          connectionString =
            "data source = localhost; Initial Catalog = Planets;" +
              "Integrated Security = SSPI";
          SqlConnection connection1 = new SqlConnection(connectionString);
          
          //Открываем соединение
          connection1.Open();
          
          SqlCommand command1 = new SqlCommand(sql, connection1);
          SqlDataReader dataReader1 = command1.ExecuteReader();
          // Организуем циклический перебор полученных записей
          //и выводим название каждой планеты в список
          while (dataReader1.Read())
          {
            listPlanets.Items.Add(dataReader1["PlanetName"]);
          }
          
          // Очистка
          dataReader1.Close();
          connection1.Close();
          /*
          
          //Вариант 3. Связывание с базой данных Access 2003 - *.mdb
          connectionString = "Provider=Microsoft.Jet.OLEDB.4.0;" +
            @"Data Source= ../../../databases/planets.mdb";
          
          //Вариант 4. Связывание с базой данных Access 2007 - *.accdb
          connectionString = "Provider=Microsoft.Ace.OLEDB.12.0;" +
            @"Data Source= ../../../databases/planets.accdb";
          
          OleDbConnection connection = new OleDbConnection(connectionString);
          connection.Open();
          OleDbCommand command = new OleDbCommand(sql, connection);
          OleDbDataReader dataReader = command.ExecuteReader();
          
          // Организуем циклический перебор полученных записей
          //и выводим название каждой планеты в список
          while (dataReader.Read())
          {
            listPlanets.Items.Add(dataReader["PlanetName"]);
          }
          
          // Очистка
          dataReader.Close();
          connection.Close();
          * */      
        }
        
        static void Main()
        {
          // Создаем и запускаем форму
          Application.Run(new SimpleDataAccess());
        }
    }

    Пример программы 4.2

    В этой программе на экран выводится несколько столбцов данных. Для их представления мы воспользуемся элементом DataGridView.

    Программа выполняет тот же запрос, что и в предыдущем примере, но помещает результат в объект DataSet, который подключается к элементу управления DataGridView, а тот автоматически отображает все данные.

    Подключение источника данных к визуальному элементу управления называется привязкой, или связыванием данных.

    using System.Windows.Forms;
    using System.Data;
    // Пространство имен для работы с базами данных SQL Server
    using System.Data.SqlClient;
    using System.Drawing;
    // Пространство имен для работы с базами данных Access
    using System.Data.OleDb;
    class DataInGrid : Form
    {
      public DataInGrid()
      {
        //Изменяем размеры формы
        this.Width = 450;
        this.Height = 400;
        
        // Указываем заголовок окна
        this.Text = "Одностороннее связывание:" +
          " база данных и элемент Grid.";
        // Добавляем элементы управления - метку и таблицу
        Label labelCaption = new Label();
        labelCaption.Text = "Планеты солнечной системы!";
        labelCaption.Location = new Point(60, 10);
        labelCaption.Width = 200;
        labelCaption.Parent = this;
        
        // Добавляем элемент DataGridView на форму
        
        DataGridView dataGridView1 = new DataGridView();
        dataGridView1.Width = 350;
        dataGridView1.Height = 250;
        dataGridView1.Location = new Point(20, 50);
        dataGridView1.DataMember = "Table";
        dataGridView1.AutoResizeColumns();
        this.Controls.Add(dataGridView1);
        
        // Формируем запрос к базе данных -
        //запрашиваем информацию о планетах
        string sql = "SELECT * FROM PLANET";
        string connectionString;
        // DataSet сохраняет данные в памяти
        //данные хранятся в виде таблиц данных DataTable
        DataSet dataSet1 = new DataSet();
        
        /*
        //Вариант 1
        // Подключаемся к базе данных SQL Server Express Edition
        // Указываем физический путь к базе данных PLANETS
        string dbLocation =
        ("../../../databases/planets.mdf");
        
        connectionString = @"data source=.\SQLEXPRESS;" +
            "User Instance=true;Integrated Security=SSPI;" +
          "AttachDBFilename=" + dbLocation;
        SqlConnection connection1 = new SqlConnection(connectionString);
        */
        /*
        //Вариант 2
        // Подключаемся к базе данных SQL Server 2005
        connectionString =
          "data source = localhost; Initial Catalog = Planets;" +
            "Integrated Security = SSPI";
        SqlConnection connection1 = new SqlConnection(connectionString);
        
        //Открываем соединение
        connection1.Open();
        
        // DataAdapter - посредник между базой данных и DataSet
        SqlDataAdapter sqlDataAdapter1 = new SqlDataAdapter();
        
        // Создаем объект DataAdapter,
        //передаем ему данные запроса
        sqlDataAdapter1.SelectCommand =
        new SqlCommand(sql, connection1);
        
        // Данные из адаптера поступают в DataSet
        sqlDataAdapter1.Fill(dataSet1);
        
        // Связываем данные с элементом DataGridView
        DataGridView1.DataSource = dataSet1;
        
        // Очистка
        connection1.Close();
        * */
        
        /*
        //Вариант 3. Связывание с базой данных Access 2003 - *.mdb
        connectionString = "Provider=Microsoft.Jet.OLEDB.4.0;" +
          @"Data Source= ../../../databases/planets.mdb";
        
        */
        //Вариант 4. Связывание с базой данных Access 2007 - *.accdb
        connectionString = "Provider=Microsoft.Ace.OLEDB.12.0;" +
          @"Data Source= ../../../databases/planets.accdb";
        
        OleDbConnection connection = new OleDbConnection(connectionString);
        connection.Open();
        
        OleDbDataAdapter dataAdapter = new OleDbDataAdapter();
        dataAdapter.SelectCommand = new OleDbCommand(sql, connection);
        
        dataAdapter.Fill(dataSet1);
        dataGridView1.DataSource = dataSet1;
        
        // Очистка
        connection.Close();
      }
      static void Main()
      {
        // Создаем и запускаем форму
        Application.Run(new DataInGrid());
      }
    }

    Пример программы 4.3

    Научившись отображать данные с помощью элемента управления DataGridView, вы, наверное, обратили внимание, что внесенные в базу изменения не сохраняются. Поэтому применим другой подход и осуществим "двухстороннюю привязку данных", которая позволит не только просматривать открывшуюся таблицу, но и вводить изменения в элемент DataGridView, добавляя новые строки, изменяя содержимое имеющихся строк и удаляя ненужные. Объекты класса DataAdapter способны выполнять как операцию Select, получая данные запроса из базы данных, так и команды Insert, Update, Delete, изменяя содержимое таблицы базы данных.

    Здесь мы позволим себе маленькую хитрость (это называется "повысить производительность труда") и не станем самостоятельно прописывать операторы UPDATE и INSERT. Пространство имен System.Data содержит небольшой, но очень полезный класс CommandBuilder, который умеет создавать команды SQL и автоматически их выполнять.

    using System;
    using System.Windows.Forms;
    using System.Data;
    // Пространство имен для работы с базами данных SQL Server
    using System.Data.SqlClient;
    using System.Drawing;
    using System.Diagnostics;
    class DataInOutGrid: Form
    {
      SqlDataAdapter dataAdapter;
      DataGridView dataGridView;
      public DataInOutGrid()
      {
        //Изменяем размеры формы
        this.Width = 450;
        this.Height = 400;
        
        // Указываем заголовок окна
        this.Text = "Двустороннее связывание:" +
          " база данных и элемент Grid.";
        // Добавляем элементы управления -
        //метку, таблицу и командную кнопку
        Label labelCaption = new Label();
        labelCaption.Text = "Планеты!";
        labelCaption.Location = new Point(60, 10);
        labelCaption.Width = 200;
        labelCaption.Parent = this;
        
        // Добавляем элемент DataGridView на форму
        
        dataGridView = new DataGridView();
        dataGridView.Width = 350;
        dataGridView.Height = 250;
        dataGridView.Location = new Point(20, 50);
        dataGridView.AutoResizeColumns();
        this.Controls.Add(dataGridView);
        
        // Добавляем командную кнопку
        Button buttonSave = new Button();
        buttonSave.Location = new Point(100, 320);
        buttonSave.Width = 220;
        buttonSave.Text = "Сохранить изменения в базе данных!";
        buttonSave.Click +=
          new System.EventHandler(ButtonSave_Click);
        buttonSave.Parent = this;
        
        // Формируем запрос к базе данных -
        //запрашиваем информацию о планетах
        string sql = "SELECT * FROM PLANET";
        string connectionString;
        // DataTable сохраняет данные в памяти как таблицу
        DataTable dataTable = new DataTable();
        /*
        //Вариант 1
        // Подключаемся к базе данных SQL Server Express Edition
        
        // Указываем физический путь к базе данных PLANETS
        string dbLocation =
        ("../../../databases/planets.mdf");
        
        connectionString = @"data source=.\SQLEXPRESS;" +
            "User Instance=true;Integrated Security=SSPI;" +
          "AttachDBFilename=" + dbLocation;
        SqlConnection connection1 = new SqlConnection(connectionString);
        */
        
        //Вариант 2
        // Подключаемся к базе данных SQL Server 2005
        connectionString =
          "data source = localhost; Initial Catalog = Planets;" +
            "Integrated Security = SSPI";
        SqlConnection connection = new SqlConnection(connectionString);
        
        //Открываем соединение
        connection.Open();
        
        //Создаем команду
        SqlCommand sqlCommand = new SqlCommand(sql, connection);
        //Создаем адаптер
        // DataAdapter - посредник между базой данных и DataSet
        dataAdapter = new SqlDataAdapter(sqlCommand);
        
        //Создаем построитель команд
        //Для адаптера становится доступной команда Update
        SqlCommandBuilder commandBuilder =
          new SqlCommandBuilder(dataAdapter);
        
        // Данные из адаптера поступают в DataTable
        dataAdapter.Fill(dataTable);
        // Связываем данные с элементом DataGridView
        dataGridView.DataSource = dataTable;
        // Очистка
        connection.Close();
      }
      
      static void Main()
      {
        // Создаем и запускаем форму
        Application.Run(new DataInOutGrid());
      }
      void ButtonSave_Click(object sender, System.EventArgs args)
      {
        try
        {
          dataAdapter.Update((DataTable)dataGridView.DataSource);
          MessageBox.Show("Изменения в базе данных выполнены!",
            "Уведомление о результатах", MessageBoxButtons.OK);
        }
        catch(Exception)
        {
          MessageBox.Show("Изменения в базе данных выполнить не удалось!",
            "Уведомление о результатах", MessageBoxButtons.OK);
        }
      }
    }

    На следующем рисунке показано содержимое базы данных, в которую добавлены две строки с названиями недавно открытых фантастических планет Солярис и Обитаемый остров (или коротко – Остров).

    Поэкспериментируйте, изменяя существующие значения и вводя новые. Нажмите кнопку "Сохранить изменения" и закройте форму. Перезапустив программу, убедитесь, что все значения были сохранены в базе данных. Если вы работаете с Access, то измените код в соответствии с образцом, приведенным в программах Example 12 и Example 13.

    Работа с XML-данными

    Классы пространства имен System.Xml позволяют работать с XML-данными разными способами. Наиболее часто выполняются следующие задачи:

  • открытие XML-документа;
  • чтение фрагмента XML-данных для извлечения некоторых значений;
  • сохранение XML-файла на диск.
  • Краткое введение в XML

    Язык XML (от англ. eXtensible Markup Language – расширяемый язык разметки) предназначен для хранения структурированных данных. Данные, хранящиеся в формате XML, можно передавать между программами. Поскольку данные в XML структурированные, в некоторых случаях использование этого формата может заменить базы данных. Кроме этого, у XML есть еще много других полезных применений.

    Язык XML широко распространен, и, скорее всего, вы уже слышали о нем. Этот язык удобно воспринимать как человеку, так и машине. Большая часть программного кода, с которыми работают различные вычислительные системы, обычным людям кажутся китайской грамотой, но XML-документы записываются почти как обычный текст.

    Например, можно составить XML-документ для хранения на диске географических данных:

    <?xml version="1.0" encoding="utf-8" ?>
    
    -<Планета>
      Земля
      - <Континент>
      Южная Америка
        <Страна столица="Рио-де-Жанейро">
          Бразилия
        </Страна>
        <Страна столица="Буэнос-Айрес">
          Аргентина
        </Страна>
    </Континент>
    
    - <Континент>
      Азия
        <Страна столица="Дели">
          Индия
        </Страна>
      <Страна столица="Бангкок">
        Тайланд
      </Страна>
     </Континент>
    </Планета>
    Каждый XML-документ начинается со строки <?xml version="1.0" encoding="utf-8" ?>. Встретив такую строку, программа будет знать, что имеет дело именно с XML

    Строки заключенные в треугольные скобки ( <> ) называются тегами. Теги могут быть любыми, и иметь произвольное количество вложений.

    Внешний блок Планета

    Вложенный блок Континент, содержащий информацию о материке Южная Америка

    Блоки более глубокого уровня вложения, содержат информацию о странах данного континента

    Еще один вложенный блок Континент

    XML весьма похож на другой язык разметки HTML, но в HTML набор тегов фиксирован, и у каждого тега есть свое строго определенное назначение и правила написания. В XML можно определять собственные теги, но при этом все равно нужно соблюдать синтаксические правила языка разметки.

    Далее мы обсудим значение двух терминов, без знания которых невозможно дальнейшее изучение языка XML.

    Элементы

    XML-документ - это запись, состоящая из отдельных элементов. Каждый элемент начинается с открывающего тега, заключенного в треугольные скобки ( <> ) – и заканчивается закрывающим тегом ( </> ).

    Имя элемента задается в открывающем теге и повторяется в закрывающем теге, а между открывающим и закрывающим тегами находится его содержание. В содержание тега могут быть вложены другие теги. Теги с одним именем нередко повторяются, даже если они не вложены один в другой.

    В приведенном выше XML-документе один из элементов с именем <Континент> имеет значение "Южная Америка". В него вложены два элемента с именем <Страна>, содержательно задающие названия стран этого континента.

    Имя элемента в открывающем теге Значение Закрывающий тег
    <Страна> Бразилия </Страна>
    <Школьник> Ваня Курочкин </Школьник>

    Атрибуты

    В открывающем теге можно задавать дополнительные свойства элемента. Для этого используются атрибуты. Каждый атрибут задается парой "имя = "значение"". Например, если для элемента <Страна> надо указать столицу, то можно создать атрибут элемента с именем "столица". А для элемента <Школьник> задать атрибуты "возраст" и "класс". В приведенном ниже примере у элемента "Страна" со значением "Аргентина" атрибут "столица" имеет значение "Буэнос-Айрес".

    Открывающий тег Значение элемента Закрывающий тег
    Имя элемента Имя атрибута Значение атрибута
    <Страна столица = "Буэнос-Айрес" > Аргентина </Страна>

    Читать подобные документы не составляет труда, а поскольку они имеют четкую структуру, то и компьютер можно научить этому без особых проблем. Например, составить такой набор инструкций: "Начать просмотр документа; при нахождении символа " < " — читать имя элемента. При нахождении символа " > " — читать значение элемента..." и так далее.

    Некоторые элементы могут иметь только атрибуты и не иметь значения и содержания. Тогда открывающий и закрывающий теги объединяются. Например, элемент <Страна> можно задать следующим образом:

    <Страна название = "Аргентина" столица = "Буэнос-Айрес" />

    Для описания элемента использовались два атрибута, но не значение элемента.

    Пример программы 4.4

    Следующая программа считывает данные из XML-файла и отображает их на форме.

    В ней используются три класса из пространства имен System.Xml:

  • XmlDocument. Объекты этого класса задают Xml-документ. При создании объекта содержимое документа может быть прочитано из файла, получено из других источников или создано в ходе работы программы.
  • XmlNodeList. Объекты этого класса могут содержать некоторый список элементов XML-документа, найденный, например, в результате поиска.
  • XmlNode. Объект этого класса задает один XML-элемент.
  • Для поиска нужных фрагментов XML-документа в программе используются так называемые выражения xPath. Они позволяют указать, какие именно элементы необходимо извлечь из XML-документа. Выражение xPath вида "/континент/страна" означает: "найти все элементы с именем "страна", вложенные в элемент с именем "континент"".

    using System;
    using System.Windows.Forms;
    using System.Drawing;
    // Пространство имен для работы с XML-данными
    using System.Xml;
    //Пространство имен для работы с выражениями xPath
    using System.Xml.XPath;
    class XmlRetriever: Form
    {
      ComboBox comboBox1;
      Button button1;
      ListBox listBox1;
      RichTextBox richTextBox1;
      XmlDocument xmlDoc;
      
      // Метод-конструктор нашего класса
      public XmlRetriever()
      {
        // Задаем заголовок и размеры окна
        this.Text = "Работа с XML-документом";
        this.Size = new Size(400, 400);
        
        // Создаем объект XmlDocument, используя xml-файл
        xmlDoc = new XmlDocument();
        xmlDoc.Load("../../docs/Planets.xml");
        
        // Создаем объект TextBox для вывода данных
        richTextBox1 = new RichTextBox();
        richTextBox1.Dock = DockStyle.Top;
        richTextBox1.AcceptsTab = true;
        richTextBox1.Height = 180;
        richTextBox1.ReadOnly = true;
        richTextBox1.BackColor = Color.Silver;
        
        // Помещаем XML-данные в элемент TextBox
        richTextBox1.Text = xmlDoc.OuterXml;
        this.Controls.Add(richTextBox1);
        
        // Создаем объект ComboBox
        // В элементы списка этого объекта записываем
        //различные выражения XPath,
        //позволяющие искать нужные элементы XML-документа
        comboBox1 = new ComboBox();
        comboBox1.Location = new Point(0, 200);
        comboBox1.Width = 300;
        comboBox1.Items.Add("/Планета");
        comboBox1.Items.Add("/Планета/Континент");
        comboBox1.Items.Add("/Планета/Континент/Страна");
        comboBox1.Items.Add(
          "/Планета/Континент/Страна[@столица='Рио-де-Жанейро']");
        comboBox1.SelectedIndex = 0;
        this.Controls.Add(comboBox1);
        
        // Создаем командную кнопку для поиска и отображения
        // соответствующих элементов Xml-документа
        button1 = new Button();
        button1.Text = "Получить данные";
        button1.Location = new Point(100, 230);
        button1.Width = 120;
        button1.Click += new EventHandler(Button1_Click);
        this.Controls.Add(button1);
        
        // Создаем элемент ListBox для отображения элементов
        listBox1 = new ListBox();
        listBox1.Dock = DockStyle.Bottom;
        listBox1.Location = new Point(10, 10);
        this.Controls.Add(listBox1);
      }
      
      static void Main()
      {
        // Создаем и запускаем новый экземпляр класса
        Application.Run(new XmlRetriever());
      }
      
      // Обработчик события, срабатывающий при нажатии кнопки
      void Button1_Click(object sender, EventArgs e)
      {
        XmlNodeList xmlNodes;
        XmlNode xmlElement;
        string elementValue;
      
        // Используем охраняемый блок try-catch,
        // что позволит в случае ошибок в выражениях XPath
        // перехватывать обработку исключений, выдавать сообщение
        // об ошибке и нормально продолжить работу приложения
        try
        {
          // Выбираем из XML-документа элементы, которые соответствуют
          // выражению XPath, заданному выбранным элементом ComboBox
          xmlNodes = xmlDoc.SelectNodes(comboBox1.Text);
        
          // Производим циклический перебор найденных элементов,
          // добавляя каждый элемент в ListBox
          listBox1.Items.Clear();
          for (int i = 0; i < xmlNodes.Count; i++)
          {
            xmlElement = xmlNodes[i];
            if (xmlElement.HasChildNodes)
            {
              elementValue = xmlElement.FirstChild.Value.Trim();
              listBox1.Items.Add(elementValue);
            }
          }
        }
        catch (XPathException ex)
        {
          const string errorMessage =
            "Ошибка в задании выражения XPath!" +
            "\r\n" + "Соответствующие данные в документе не найдены!" +
            "\r\n" + "Попробуйте задать другое выражение!";
          MessageBox.Show(errorMessage +"\r\n" + ex.Message);
        }
      }
    }

    Программа отображает исходный XML-файл в элементе управления RichTextBox. Далее из списка элементов ComboBox можно выбрать одно из выражений xPath и нажать на командную кнопку. В результате в элемент управления ListBox будут выведены элементы Xml-документа, заданные выражением XPath. Вы можете задать собственное выражение XPath в элементе ComboBox. После запуска программы поэкспериментируйте с вводом и выбором выражения xPath, после чего нажмите кнопку "Получить данные".

    Страницы:

    Введение в работу с базами данных

    Большинство приложений работают с базами данных. Любой программист из крупной компании подтвердит, что роль баз данных в мире вычислительных технологий очень велика. Обладая умением оперировать с базами данных, можно создавать самые разнообразные и действительно полезные приложения.

    Возможно, у вас на компьютере уже установлена система управления базами данных, например, Microsoft Access. Лучшая альтернатива – это Microsoft SQL Server Express Edition, с помощью которого вы научитесь работать с базами данных SQL Server, используемыми во многих крупнейших компаниях по всему миру. SQL Server Express включен в пакет установки Visual C# Express, так что, скорее всего, на вашем компьютере он уже установлен.

    Для работы с базами данных в библиотеке .NET Framework предусмотрены классы пространства имен System.Data. База данных в корне отличается от таких объектов, как изображения или документы текстовых редакторов, которые часто называют неструктурированными. Информация в базе данных структурирована и обычно хранится в таблицах, а каждая таблица состоит из строк и столбцов.

    В программировании строки называют записями, а столбцы задают поля записи. Столбец таблицы определяет тип данных, хранимых в поле записи.

    Ниже представлена таблица базы данных, содержащая информацию о планетах. Она имеет следующие столбцы: PlanetName (название планеты), DistanceFromSun (расстояние до Солнца) и Inhabitants (обитатели).

    Planet
    PlanetName DistanceFromSun (единица измерения – тысяча километров) Inhabitants
    Меркурий 57909 Меркуриане
    Венера 108200 Венериане
    Земля 149600 Земляне
    Марс 227940 Марсиане
    Юпитер 778400 Юпитериане
    Знок 7208100 Знокиане
    Сатурн 1423600 Сатурниане
    Уран 2867000 Ураниане
    Нептун 4488400 Нептуниане
    Плутон 5909600 Плутониане

    Из таблицы видно, что, например, Венера находится на расстоянии 108 200 тысяч километров от Солнца, а существа, ее населяющие, называются венериане.

    Вот еще одна таблица, в которой содержатся сведения о ежегодной численности обитателей разных планет.

    Эта совершенно секретная информация, нигде ранее не обнародованная, была получена с инопланетного звездолета, потерпевшего крушение в самой глубине пустыни Гоби. Иметь возможность ознакомиться с ней – большая честь. Очевидно, представители инопланетной цивилизации тоже используют базы данных SQL Server, что и позволило нам привести эти сведения в качестве примера.

    Population
    PlanetName Year Population
    Меркурий 2008 40000
    Венера 2008 25
    Земля 2008 6000000000
    Марс 2008 450000
    Юпитер 2008 8326300200
    Знок 2008 325000
    Сатурн 2008 1000000
    Уран 2008 7849345700
    Нептун 2008 <NULL>
    Плутон 2008 <NULL>
    Меркурий 2009 35000
    Венера 2009 3
    Земля 2009 6500000000
    Марс 2009 326800
    Юпитер 2009 8451780500
    Знок 2009 8700
    Сатурн 2009 750000
    Уран 2009 8237456000
    Нептун 2009 <NULL>
    Плутон 2009 <NULL>

    Если продолжить разговор о Венере, то, обратите внимание, что в 2008 г. на Венере обитало 25 венериан, а через год, вероятно, в результате извержений вулканов, их осталось всего трое.

    Не следует путать базы данных с электронными таблицами. Хотя способ представления данных в электронных таблицах внешне похож на тот, что использовался в приведенных выше примерах, обработка данных происходит в них иначе.

    Язык SQL

    Существует множество разнообразных систем управления базами данных: Microsoft Access, Oracle, DB2, Microsoft SQL Server, Informix, mySQL, и это далеко не полный список. А нам необходимо обратиться к базе данных из программы на языке C# и "объяснить" ей, что мы ищем.

    Проще всего включить в код C# фрагмент на "языке базы данных", с помощью которого выполняется запрос к базе данных на получение нужных столбцов и строк.

    (По правде говоря, существует еще и промежуточный уровень – ADO.NET, но сейчас мы не станем заострять на нем внимание.)

    Много лет назад специалисты по базам данных договорились об использовании "единого языка баз данных", который понимали бы большинство существующих баз данных. Они назвали его SQL (от англ. Structured Query Language — язык структурированных запросов). Не следует путать язык SQL с системой управления базами данных SQL Server, разработанной корпорацией Microsoft. Язык SQL поддерживают системы управления базами данных (СУБД), выпускаемые самыми разными производителями.

    Приступая к разговору о том, как использовать C# при работе с базами данных, сначала познакомимся с основами языка SQL. Ниже приведены примеры операторов на языке SQL и описывается результат их выполнения.

    Основными командами SQL являются:

  • SELECT (для выбора некоторых данных);
  • INSERT (для добавления новых данных);
  • UPDATE (для изменения информации, уже существующей в базе данных).
  • Приведем примеры каждой команды.

    Как правило, оператор SELECT записывается следующим образом:

    SELECT <имена извлекаемых столбцов>
    FROM <имена одной или нескольких таблиц базы данных>
    WHERE <условие выбора>

    Рассмотрим пример выбора данных оператором SELECT:

    SELECT * FROM PLANET

    Символ звездочка * означает выбор всех столбцов таблицы. Поэтому данный оператор вернет из базы данных всю таблицу Planet со всеми строками и столбцами.

    Рассмотрим оператор

    SELECT PlanetName, Inhabitants FROM PLANET

    Этот запрос возвращает столбцы PlanetName и Inhabitants со всеми строками из таблицы PLANET.

    PlanetName Inhabitants
    Меркурий Меркуриане
    Венера Венериане
    Земля Земляне
    Марс Марсиане
    Юпитер Юпитериане
    Знок Знокиане
    Сатурн Сатурниане
    Уран Ураниане
    Нептун Нептуниане
    Плутон Плутониане

    Запрос

    SELECT PlanetName, Inhabitants FROM PLANET
    WHERE PlanetName='Венера'

    возвращает столбцы PlanetName и Inhabitants из таблицы PLANET. В результат его выполнения будут включены только те строки, которые содержат значение Венера в столбце PlanetName.

    PlanetName Inhabitants
    Венера Венериане

    Запрос:

    SELECT PlanetName, Population FROM POPULATION
    WHERE Population<100000

    возвращает из таблицы POPULATION строки столбцов PlanetName и Population, для которых значение столбца Population меньше 100000.

    PlanetName Population
    Меркурий 40000
    Венера 25
    Нептун <NULL>
    Плутон <NULL>
    Меркурий 35000
    Венера 3
    Знок 8700
    Нептун <NULL>
    Плутон <NULL>

    Как правило, оператор INSERT записывается следующим образом:

    INSERT INTO <таблица базы данных, к которой добавляются строки>
    (<названия столбцов, в которые будут добавляться значения>)
    VALUES (<значения, которые будут вставлены в указанные столбцы>)

    Пример:

    INSERT INTO PLANET (PlanetName, DistanceFromSun, Inhabitants)
    VALUES (Флафф, 23500000, 'Флаффиане')

    Оператор INSERT добавляет в таблицу PLANET новую строку. Он не возвращает какого-либо результата в программу, но после его выполнения таблица примет вот такой вид:

    PlanetName DistanceFromSun Inhabitants
    Меркурий 57909 Меркуриане
    Венера 108200 Венериане
    Земля 149600 Земляне
    Марс 227940 Марсиане
    Юпитер 778400 Юпитериане
    Знок 7208100 Знокиане
    Сатурн 1423600 Сатурниане
    Уран 2867000 Ураниане
    Нептун 4488400 Нептуниане
    Плутон 5909600 Плутониане
    Флафф 23500000 Флаффиане

    Оператор UPDATE записывается следующим образом:

    UPDATE <таблица базы данных, в которую вносятся изменения>
    SET <названия столбцов, в которые необходимо внести изменения> = <новые значения>
    WHERE <условия>

    Пример:

    UPDATE PLANET SET PlanetName= 'Стафф', Inhabitants='Стаффиане' WHERE PlanetName='Флафф'

    Оператор изменяет некоторые значения в той строке, где столбец PlanetName имеет значение "Флафф". Результат выполнения операции программе не возвращается, но таблица примет вот такой вид:

    PlanetName DistanceFromSun Inhabitants
    Меркурий 57909 Меркуриане
    Венера 108200 Венериане
    Земля 149600 Земляне
    Марс 227940 Марсиане
    Юпитер 778400 Юпитериане
    Знок 7208100 Знокиане
    Сатурн 1423600 Сатурниане
    Уран 2867000 Ураниане
    Нептун 4488400 Нептуниане
    Плутон 5909600 Плутониане
    Стафф 23500000 Стаффиане

    Связи и объединение таблиц базы данных

    Если рассмотреть таблицы внимательно, то можно заметить, что между таблицами PLANET и POPULATION существует связь: и в той и в другой есть столбец с именем PlanetName, который связывает обе таблицы. Благодаря этой связи можно собрать всю информацию об определенной планете.

    Например, можно выбрать из обеих таблиц все строки, касающиеся Венеры:

    PLANET
    PlanetName DistanceFromSun Inhabitants
    Венера 108200 Венериане
    POPULATION
    PlanetName Year Population
    Венера 2008 25
    Венера 2009 3

    А затем объединить полученные данные в одну большую таблицу:

    SELECT *
    FROM PLANET INNER JOIN POPULATION ON PLANET.PlanetName=POPULATION.planetName
    WHERE PlanetName='Венера'
    PLANETS_AND_POPULATION
    PlanetName DistanceFromSun Inhabitants Year Population
    Венера 108200 Венериане 2008 25
    Венера 108200 Венериане 2009 3

    Особенности разных СУБД

    При работе с определенной СУБД необходимо учитывать ее особенности. С этой целью вводится понятие "провайдер данных" – у каждой СУБД он свой. С точки зрения программиста провайдер данных — это набор классов, обеспечивающих связь с базой и осуществляющих доступ к данным. Так, например, за связь с базой данных Microsoft SQL Server отвечает класс SqlConnection, а за связь с базой данных Access — OleDbConnection. Первый является частью провайдера данных SQLDataProvider, второй — провайдера данных OLEDbProvider.

    Программный код меняется в зависимости от того, с какой базой предстоит работать. Для демонстрации возможностей использования баз данных, работающих под управлением различных СУБД, мы создали базу данных Planets в Microsoft SQL Server и в Access. Поскольку формат базы данных в Access 2007 отличается от формата, принятого в предыдущих версиях, реализация выполнена для версий Access 2007 и Access 2003. Естественно, что все особенности построения баз данных находят отражение в программном коде.

    Три варианта базы данных Planets помещены в каталог с именем databases. Файлы Planets.mdf и Planets.ldf, задают базу данных SQL Server, файл Planets.accdb создан для базы данных Access 2007, а Planets.mdb — для базы данных Access 2003.

    В программном коде указывается путь к файлам базы данных, поэтому папка databases должна находиться в том же каталоге, где находится программа, задающая решение, — в нашем случае это файл Examples.sln.

    При работе с базой данных SQL Server программный код зависит от того, с какой версией СУБД приходится работать — с Microsoft SQL Server или Microsoft SQL Server Express Edition.

    В приведенном ниже примере показаны четыре возможных варианта работы:

  • работа с Microsoft SQL Server Express Edition;
  • работа с Microsoft SQL Server;
  • работа с Access 2003;
  • работа с Access 2007.
  • Три варианта закомментированы, а один готов к использованию, в данном тексте это вариант работы с Microsoft SQL Server. В зависимости от того, что установлено на компьютере читателя, следует нужный вариант раскомментировать, а ненужный — закомментировать.

    У большинства пользователей на компьютерах установлен комплект Microsoft Office, возможно, в нем имеется и приложение Access, так что для начала можно поработать с базами данных, подготовленными в этом приложении.

    Когда вам понадобятся более широкие возможности программирования, мы рекомендуем вам установить SQL Server Express. К тому же умение работать с SQL Server гораздо выше ценится в деловой сфере, и чем скорее вы освоите этот инструмент, тем лучше. Загрузить его можно бесплатно с сайта Microsoft: http://www.microsoft.com/.

    Обращение к базам данных из программы, написанной на языке C#

    Далее в трех примерах программ на C# мы будем использовать классы Connection, Command, DataReader, DataAdapter. Префиксы Sql и OleDb указывают на то, с каким вариантом базы данных Planets мы работаем.

    Пример программы 4.1

    Следующая программа подключается к базе данных и посылает ей SQL-запрос. Затем выполняется несколько циклов получения результата запроса, после чего полученные результаты передаются в элемент управления ListBox и отображаются в списке.

    using System.Windows.Forms;
    using System.Data;
    // Пространство имен для работы с базами данных SQL Server
    using System.Data.SqlClient;
    using System.Drawing;
    // Пространство имен для работы с базами данных Access
    using System.Data.OleDb;
    class SimpleDataAccess : Form
    {
      public SimpleDataAccess()
        {
          // Указываем заголовок окна
          this.Text = "Работа с базой данных. Чтение данных.";
          // Добавляем элементы управления - метку и список
          Label labelCaption = new Label();
          labelCaption.Text = "Планеты солнечной системы!";
          labelCaption.Location = new Point(30, 10);
          labelCaption.Width = 200;
          labelCaption.Parent = this;
          
          ListBox listPlanets = new ListBox();
          listPlanets.Location = new Point(30, 50);
          listPlanets.Width = 100;
          listPlanets.Parent = this;
          
          // Формируем запрос к базе данных -
          //запрашиваем информацию о планетах
          string sql = "SELECT * FROM PLANET";
          string connectionString;
          
          /*
          //Вариант 1
          // Подключаемся к базе данных SQL Server Express Edition
          
          // Указываем физический путь к базе данных PLANETS
          string dbLocation =
          ("../../../databases/planets.mdf");
          
          connectionString = @"data source=.\SQLEXPRESS;" +
          "User Instance=true;Integrated Security=SSPI;" +
          "AttachDBFilename=" + dbLocation;
          SqlConnection connection1 = new SqlConnection(connectionString);
          */
          
          //Вариант 2
          // Подключаемся к базе данных SQL Server 2005
          connectionString =
            "data source = localhost; Initial Catalog = Planets;" +
              "Integrated Security = SSPI";
          SqlConnection connection1 = new SqlConnection(connectionString);
          
          //Открываем соединение
          connection1.Open();
          
          SqlCommand command1 = new SqlCommand(sql, connection1);
          SqlDataReader dataReader1 = command1.ExecuteReader();
          // Организуем циклический перебор полученных записей
          //и выводим название каждой планеты в список
          while (dataReader1.Read())
          {
            listPlanets.Items.Add(dataReader1["PlanetName"]);
          }
          
          // Очистка
          dataReader1.Close();
          connection1.Close();
          /*
          
          //Вариант 3. Связывание с базой данных Access 2003 - *.mdb
          connectionString = "Provider=Microsoft.Jet.OLEDB.4.0;" +
            @"Data Source= ../../../databases/planets.mdb";
          
          //Вариант 4. Связывание с базой данных Access 2007 - *.accdb
          connectionString = "Provider=Microsoft.Ace.OLEDB.12.0;" +
            @"Data Source= ../../../databases/planets.accdb";
          
          OleDbConnection connection = new OleDbConnection(connectionString);
          connection.Open();
          OleDbCommand command = new OleDbCommand(sql, connection);
          OleDbDataReader dataReader = command.ExecuteReader();
          
          // Организуем циклический перебор полученных записей
          //и выводим название каждой планеты в список
          while (dataReader.Read())
          {
            listPlanets.Items.Add(dataReader["PlanetName"]);
          }
          
          // Очистка
          dataReader.Close();
          connection.Close();
          * */      
        }
        
        static void Main()
        {
          // Создаем и запускаем форму
          Application.Run(new SimpleDataAccess());
        }
    }

    Пример программы 4.2

    В этой программе на экран выводится несколько столбцов данных. Для их представления мы воспользуемся элементом DataGridView.

    Программа выполняет тот же запрос, что и в предыдущем примере, но помещает результат в объект DataSet, который подключается к элементу управления DataGridView, а тот автоматически отображает все данные.

    Подключение источника данных к визуальному элементу управления называется привязкой, или связыванием данных.

    using System.Windows.Forms;
    using System.Data;
    // Пространство имен для работы с базами данных SQL Server
    using System.Data.SqlClient;
    using System.Drawing;
    // Пространство имен для работы с базами данных Access
    using System.Data.OleDb;
    class DataInGrid : Form
    {
      public DataInGrid()
      {
        //Изменяем размеры формы
        this.Width = 450;
        this.Height = 400;
        
        // Указываем заголовок окна
        this.Text = "Одностороннее связывание:" +
          " база данных и элемент Grid.";
        // Добавляем элементы управления - метку и таблицу
        Label labelCaption = new Label();
        labelCaption.Text = "Планеты солнечной системы!";
        labelCaption.Location = new Point(60, 10);
        labelCaption.Width = 200;
        labelCaption.Parent = this;
        
        // Добавляем элемент DataGridView на форму
        
        DataGridView dataGridView1 = new DataGridView();
        dataGridView1.Width = 350;
        dataGridView1.Height = 250;
        dataGridView1.Location = new Point(20, 50);
        dataGridView1.DataMember = "Table";
        dataGridView1.AutoResizeColumns();
        this.Controls.Add(dataGridView1);
        
        // Формируем запрос к базе данных -
        //запрашиваем информацию о планетах
        string sql = "SELECT * FROM PLANET";
        string connectionString;
        // DataSet сохраняет данные в памяти
        //данные хранятся в виде таблиц данных DataTable
        DataSet dataSet1 = new DataSet();
        
        /*
        //Вариант 1
        // Подключаемся к базе данных SQL Server Express Edition
        // Указываем физический путь к базе данных PLANETS
        string dbLocation =
        ("../../../databases/planets.mdf");
        
        connectionString = @"data source=.\SQLEXPRESS;" +
            "User Instance=true;Integrated Security=SSPI;" +
          "AttachDBFilename=" + dbLocation;
        SqlConnection connection1 = new SqlConnection(connectionString);
        */
        /*
        //Вариант 2
        // Подключаемся к базе данных SQL Server 2005
        connectionString =
          "data source = localhost; Initial Catalog = Planets;" +
            "Integrated Security = SSPI";
        SqlConnection connection1 = new SqlConnection(connectionString);
        
        //Открываем соединение
        connection1.Open();
        
        // DataAdapter - посредник между базой данных и DataSet
        SqlDataAdapter sqlDataAdapter1 = new SqlDataAdapter();
        
        // Создаем объект DataAdapter,
        //передаем ему данные запроса
        sqlDataAdapter1.SelectCommand =
        new SqlCommand(sql, connection1);
        
        // Данные из адаптера поступают в DataSet
        sqlDataAdapter1.Fill(dataSet1);
        
        // Связываем данные с элементом DataGridView
        DataGridView1.DataSource = dataSet1;
        
        // Очистка
        connection1.Close();
        * */
        
        /*
        //Вариант 3. Связывание с базой данных Access 2003 - *.mdb
        connectionString = "Provider=Microsoft.Jet.OLEDB.4.0;" +
          @"Data Source= ../../../databases/planets.mdb";
        
        */
        //Вариант 4. Связывание с базой данных Access 2007 - *.accdb
        connectionString = "Provider=Microsoft.Ace.OLEDB.12.0;" +
          @"Data Source= ../../../databases/planets.accdb";
        
        OleDbConnection connection = new OleDbConnection(connectionString);
        connection.Open();
        
        OleDbDataAdapter dataAdapter = new OleDbDataAdapter();
        dataAdapter.SelectCommand = new OleDbCommand(sql, connection);
        
        dataAdapter.Fill(dataSet1);
        dataGridView1.DataSource = dataSet1;
        
        // Очистка
        connection.Close();
      }
      static void Main()
      {
        // Создаем и запускаем форму
        Application.Run(new DataInGrid());
      }
    }

    Пример программы 4.3

    Научившись отображать данные с помощью элемента управления DataGridView, вы, наверное, обратили внимание, что внесенные в базу изменения не сохраняются. Поэтому применим другой подход и осуществим "двухстороннюю привязку данных", которая позволит не только просматривать открывшуюся таблицу, но и вводить изменения в элемент DataGridView, добавляя новые строки, изменяя содержимое имеющихся строк и удаляя ненужные. Объекты класса DataAdapter способны выполнять как операцию Select, получая данные запроса из базы данных, так и команды Insert, Update, Delete, изменяя содержимое таблицы базы данных.

    Здесь мы позволим себе маленькую хитрость (это называется "повысить производительность труда") и не станем самостоятельно прописывать операторы UPDATE и INSERT. Пространство имен System.Data содержит небольшой, но очень полезный класс CommandBuilder, который умеет создавать команды SQL и автоматически их выполнять.

    using System;
    using System.Windows.Forms;
    using System.Data;
    // Пространство имен для работы с базами данных SQL Server
    using System.Data.SqlClient;
    using System.Drawing;
    using System.Diagnostics;
    class DataInOutGrid: Form
    {
      SqlDataAdapter dataAdapter;
      DataGridView dataGridView;
      public DataInOutGrid()
      {
        //Изменяем размеры формы
        this.Width = 450;
        this.Height = 400;
        
        // Указываем заголовок окна
        this.Text = "Двустороннее связывание:" +
          " база данных и элемент Grid.";
        // Добавляем элементы управления -
        //метку, таблицу и командную кнопку
        Label labelCaption = new Label();
        labelCaption.Text = "Планеты!";
        labelCaption.Location = new Point(60, 10);
        labelCaption.Width = 200;
        labelCaption.Parent = this;
        
        // Добавляем элемент DataGridView на форму
        
        dataGridView = new DataGridView();
        dataGridView.Width = 350;
        dataGridView.Height = 250;
        dataGridView.Location = new Point(20, 50);
        dataGridView.AutoResizeColumns();
        this.Controls.Add(dataGridView);
        
        // Добавляем командную кнопку
        Button buttonSave = new Button();
        buttonSave.Location = new Point(100, 320);
        buttonSave.Width = 220;
        buttonSave.Text = "Сохранить изменения в базе данных!";
        buttonSave.Click +=
          new System.EventHandler(ButtonSave_Click);
        buttonSave.Parent = this;
        
        // Формируем запрос к базе данных -
        //запрашиваем информацию о планетах
        string sql = "SELECT * FROM PLANET";
        string connectionString;
        // DataTable сохраняет данные в памяти как таблицу
        DataTable dataTable = new DataTable();
        /*
        //Вариант 1
        // Подключаемся к базе данных SQL Server Express Edition
        
        // Указываем физический путь к базе данных PLANETS
        string dbLocation =
        ("../../../databases/planets.mdf");
        
        connectionString = @"data source=.\SQLEXPRESS;" +
            "User Instance=true;Integrated Security=SSPI;" +
          "AttachDBFilename=" + dbLocation;
        SqlConnection connection1 = new SqlConnection(connectionString);
        */
        
        //Вариант 2
        // Подключаемся к базе данных SQL Server 2005
        connectionString =
          "data source = localhost; Initial Catalog = Planets;" +
            "Integrated Security = SSPI";
        SqlConnection connection = new SqlConnection(connectionString);
        
        //Открываем соединение
        connection.Open();
        
        //Создаем команду
        SqlCommand sqlCommand = new SqlCommand(sql, connection);
        //Создаем адаптер
        // DataAdapter - посредник между базой данных и DataSet
        dataAdapter = new SqlDataAdapter(sqlCommand);
        
        //Создаем построитель команд
        //Для адаптера становится доступной команда Update
        SqlCommandBuilder commandBuilder =
          new SqlCommandBuilder(dataAdapter);
        
        // Данные из адаптера поступают в DataTable
        dataAdapter.Fill(dataTable);
        // Связываем данные с элементом DataGridView
        dataGridView.DataSource = dataTable;
        // Очистка
        connection.Close();
      }
      
      static void Main()
      {
        // Создаем и запускаем форму
        Application.Run(new DataInOutGrid());
      }
      void ButtonSave_Click(object sender, System.EventArgs args)
      {
        try
        {
          dataAdapter.Update((DataTable)dataGridView.DataSource);
          MessageBox.Show("Изменения в базе данных выполнены!",
            "Уведомление о результатах", MessageBoxButtons.OK);
        }
        catch(Exception)
        {
          MessageBox.Show("Изменения в базе данных выполнить не удалось!",
            "Уведомление о результатах", MessageBoxButtons.OK);
        }
      }
    }

    На следующем рисунке показано содержимое базы данных, в которую добавлены две строки с названиями недавно открытых фантастических планет Солярис и Обитаемый остров (или коротко – Остров).

    Поэкспериментируйте, изменяя существующие значения и вводя новые. Нажмите кнопку "Сохранить изменения" и закройте форму. Перезапустив программу, убедитесь, что все значения были сохранены в базе данных. Если вы работаете с Access, то измените код в соответствии с образцом, приведенным в программах Example 12 и Example 13.

    Работа с XML-данными

    Классы пространства имен System.Xml позволяют работать с XML-данными разными способами. Наиболее часто выполняются следующие задачи:

  • открытие XML-документа;
  • чтение фрагмента XML-данных для извлечения некоторых значений;
  • сохранение XML-файла на диск.
  • Краткое введение в XML

    Язык XML (от англ. eXtensible Markup Language – расширяемый язык разметки) предназначен для хранения структурированных данных. Данные, хранящиеся в формате XML, можно передавать между программами. Поскольку данные в XML структурированные, в некоторых случаях использование этого формата может заменить базы данных. Кроме этого, у XML есть еще много других полезных применений.

    Язык XML широко распространен, и, скорее всего, вы уже слышали о нем. Этот язык удобно воспринимать как человеку, так и машине. Большая часть программного кода, с которыми работают различные вычислительные системы, обычным людям кажутся китайской грамотой, но XML-документы записываются почти как обычный текст.

    Например, можно составить XML-документ для хранения на диске географических данных:

    <?xml version="1.0" encoding="utf-8" ?>
    
    -<Планета>
      Земля
      - <Континент>
      Южная Америка
        <Страна столица="Рио-де-Жанейро">
          Бразилия
        </Страна>
        <Страна столица="Буэнос-Айрес">
          Аргентина
        </Страна>
    </Континент>
    
    - <Континент>
      Азия
        <Страна столица="Дели">
          Индия
        </Страна>
      <Страна столица="Бангкок">
        Тайланд
      </Страна>
     </Континент>
    </Планета>
    Каждый XML-документ начинается со строки <?xml version="1.0" encoding="utf-8" ?>. Встретив такую строку, программа будет знать, что имеет дело именно с XML

    Строки заключенные в треугольные скобки ( <> ) называются тегами. Теги могут быть любыми, и иметь произвольное количество вложений.

    Внешний блок Планета

    Вложенный блок Континент, содержащий информацию о материке Южная Америка

    Блоки более глубокого уровня вложения, содержат информацию о странах данного континента

    Еще один вложенный блок Континент

    XML весьма похож на другой язык разметки HTML, но в HTML набор тегов фиксирован, и у каждого тега есть свое строго определенное назначение и правила написания. В XML можно определять собственные теги, но при этом все равно нужно соблюдать синтаксические правила языка разметки.

    Далее мы обсудим значение двух терминов, без знания которых невозможно дальнейшее изучение языка XML.

    Элементы

    XML-документ - это запись, состоящая из отдельных элементов. Каждый элемент начинается с открывающего тега, заключенного в треугольные скобки ( <> ) – и заканчивается закрывающим тегом ( </> ).

    Имя элемента задается в открывающем теге и повторяется в закрывающем теге, а между открывающим и закрывающим тегами находится его содержание. В содержание тега могут быть вложены другие теги. Теги с одним именем нередко повторяются, даже если они не вложены один в другой.

    В приведенном выше XML-документе один из элементов с именем <Континент> имеет значение "Южная Америка". В него вложены два элемента с именем <Страна>, содержательно задающие названия стран этого континента.

    Имя элемента в открывающем теге Значение Закрывающий тег
    <Страна> Бразилия </Страна>
    <Школьник> Ваня Курочкин </Школьник>

    Атрибуты

    В открывающем теге можно задавать дополнительные свойства элемента. Для этого используются атрибуты. Каждый атрибут задается парой "имя = "значение"". Например, если для элемента <Страна> надо указать столицу, то можно создать атрибут элемента с именем "столица". А для элемента <Школьник> задать атрибуты "возраст" и "класс". В приведенном ниже примере у элемента "Страна" со значением "Аргентина" атрибут "столица" имеет значение "Буэнос-Айрес".

    Открывающий тег Значение элемента Закрывающий тег
    Имя элемента Имя атрибута Значение атрибута
    <Страна столица = "Буэнос-Айрес" > Аргентина </Страна>

    Читать подобные документы не составляет труда, а поскольку они имеют четкую структуру, то и компьютер можно научить этому без особых проблем. Например, составить такой набор инструкций: "Начать просмотр документа; при нахождении символа " < " — читать имя элемента. При нахождении символа " > " — читать значение элемента..." и так далее.

    Некоторые элементы могут иметь только атрибуты и не иметь значения и содержания. Тогда открывающий и закрывающий теги объединяются. Например, элемент <Страна> можно задать следующим образом:

    <Страна название = "Аргентина" столица = "Буэнос-Айрес" />

    Для описания элемента использовались два атрибута, но не значение элемента.

    Пример программы 4.4

    Следующая программа считывает данные из XML-файла и отображает их на форме.

    В ней используются три класса из пространства имен System.Xml:

  • XmlDocument. Объекты этого класса задают Xml-документ. При создании объекта содержимое документа может быть прочитано из файла, получено из других источников или создано в ходе работы программы.
  • XmlNodeList. Объекты этого класса могут содержать некоторый список элементов XML-документа, найденный, например, в результате поиска.
  • XmlNode. Объект этого класса задает один XML-элемент.
  • Для поиска нужных фрагментов XML-документа в программе используются так называемые выражения xPath. Они позволяют указать, какие именно элементы необходимо извлечь из XML-документа. Выражение xPath вида "/континент/страна" означает: "найти все элементы с именем "страна", вложенные в элемент с именем "континент"".

    using System;
    using System.Windows.Forms;
    using System.Drawing;
    // Пространство имен для работы с XML-данными
    using System.Xml;
    //Пространство имен для работы с выражениями xPath
    using System.Xml.XPath;
    class XmlRetriever: Form
    {
      ComboBox comboBox1;
      Button button1;
      ListBox listBox1;
      RichTextBox richTextBox1;
      XmlDocument xmlDoc;
      
      // Метод-конструктор нашего класса
      public XmlRetriever()
      {
        // Задаем заголовок и размеры окна
        this.Text = "Работа с XML-документом";
        this.Size = new Size(400, 400);
        
        // Создаем объект XmlDocument, используя xml-файл
        xmlDoc = new XmlDocument();
        xmlDoc.Load("../../docs/Planets.xml");
        
        // Создаем объект TextBox для вывода данных
        richTextBox1 = new RichTextBox();
        richTextBox1.Dock = DockStyle.Top;
        richTextBox1.AcceptsTab = true;
        richTextBox1.Height = 180;
        richTextBox1.ReadOnly = true;
        richTextBox1.BackColor = Color.Silver;
        
        // Помещаем XML-данные в элемент TextBox
        richTextBox1.Text = xmlDoc.OuterXml;
        this.Controls.Add(richTextBox1);
        
        // Создаем объект ComboBox
        // В элементы списка этого объекта записываем
        //различные выражения XPath,
        //позволяющие искать нужные элементы XML-документа
        comboBox1 = new ComboBox();
        comboBox1.Location = new Point(0, 200);
        comboBox1.Width = 300;
        comboBox1.Items.Add("/Планета");
        comboBox1.Items.Add("/Планета/Континент");
        comboBox1.Items.Add("/Планета/Континент/Страна");
        comboBox1.Items.Add(
          "/Планета/Континент/Страна[@столица='Рио-де-Жанейро']");
        comboBox1.SelectedIndex = 0;
        this.Controls.Add(comboBox1);
        
        // Создаем командную кнопку для поиска и отображения
        // соответствующих элементов Xml-документа
        button1 = new Button();
        button1.Text = "Получить данные";
        button1.Location = new Point(100, 230);
        button1.Width = 120;
        button1.Click += new EventHandler(Button1_Click);
        this.Controls.Add(button1);
        
        // Создаем элемент ListBox для отображения элементов
        listBox1 = new ListBox();
        listBox1.Dock = DockStyle.Bottom;
        listBox1.Location = new Point(10, 10);
        this.Controls.Add(listBox1);
      }
      
      static void Main()
      {
        // Создаем и запускаем новый экземпляр класса
        Application.Run(new XmlRetriever());
      }
      
      // Обработчик события, срабатывающий при нажатии кнопки
      void Button1_Click(object sender, EventArgs e)
      {
        XmlNodeList xmlNodes;
        XmlNode xmlElement;
        string elementValue;
      
        // Используем охраняемый блок try-catch,
        // что позволит в случае ошибок в выражениях XPath
        // перехватывать обработку исключений, выдавать сообщение
        // об ошибке и нормально продолжить работу приложения
        try
        {
          // Выбираем из XML-документа элементы, которые соответствуют
          // выражению XPath, заданному выбранным элементом ComboBox
          xmlNodes = xmlDoc.SelectNodes(comboBox1.Text);
        
          // Производим циклический перебор найденных элементов,
          // добавляя каждый элемент в ListBox
          listBox1.Items.Clear();
          for (int i = 0; i < xmlNodes.Count; i++)
          {
            xmlElement = xmlNodes[i];
            if (xmlElement.HasChildNodes)
            {
              elementValue = xmlElement.FirstChild.Value.Trim();
              listBox1.Items.Add(elementValue);
            }
          }
        }
        catch (XPathException ex)
        {
          const string errorMessage =
            "Ошибка в задании выражения XPath!" +
            "\r\n" + "Соответствующие данные в документе не найдены!" +
            "\r\n" + "Попробуйте задать другое выражение!";
          MessageBox.Show(errorMessage +"\r\n" + ex.Message);
        }
      }
    }

    Программа отображает исходный XML-файл в элементе управления RichTextBox. Далее из списка элементов ComboBox можно выбрать одно из выражений xPath и нажать на командную кнопку. В результате в элемент управления ListBox будут выведены элементы Xml-документа, заданные выражением XPath. Вы можете задать собственное выражение XPath в элементе ComboBox. После запуска программы поэкспериментируйте с вводом и выбором выражения xPath, после чего нажмите кнопку "Получить данные".

    Вернуться к учебному плану