ADO.NET. Управление базами данных. Связь по схеме OLE DB провайдера. Коррекция стилей DataGridView, страница 21

Адаптер хорош для чтения данных, но обновлять данные лучше с помощью обычных команд. Это замечание не относится к тем случаям, когда работа ведется только с одной таблицей, или когда все поля данных определяются пользователем (нет автоматических ключей).

Преже всего нам следует научиться работать с объектами DbCommand и DbDataReader, которые позволяют более тонко и эффективно управлять процессом чтения и обновления данных.

Объекты DbDataReader

Класс DataSet — это мощный и ресурсоемкий инструмент работы с данными. Если необходимо обратиться к таблице, выбрать произвольное множество ее данных (result set), изменить их, взять под контроль все детали процесса их обновления, то более эффективным способом является использование классов, реализующих функциональность DbCommand и DbDataReader. Эффективность такого подхода становится еще выше, если требуется отображать только часть всего множества колонок таблицы.

Заметьте, что класс DbDataReader является абстрактным. Вместо него вы работаете с классами: SqlDataReader, OleDbDataReader, OdbcDataReader и OracleDataReader. Все они реализуют стандартное поведение, заданное интерфейсом IDataReader и другими интерфейсами, как показано ниже.

public abstract class DbDataReader : MarshalByRefObject, IDataReader, IDisposable, IDataRecord, IEnumerable

Широкое использование интерфейсов является важной и весьма удобной на практике отличительной особенностью ADO.NET. Это позволяет писать код, не зависящий от типа провайдера данных. Мы лишь наметим пути реализации этого подхода.

Интерфейс IDataReader имеет четыре метода: GetSchemaTable, Read, NextResult и Close. Объект одного из классов семейства DbDataReader создается с помощью метода ExecuteReader. Этот метод определен в интерфейсе IDbCommand.

·  Метод ExecuteReader выполняет команду Select и помещает результат в result-set. DbDataReader ведет себя, как курсор множества result-set. Свойство HasRows DbDataReader возвращвет true, если result set не пуст.

·  Далее идет работа с объектом DbDataReader. Каждый вызов метода Read выбирает одну строку из прочитанного result-set и возвращает булевский флаг, означающий успех операции. Обычно чтение производится в цикле, пока метод Read не возратит false.

·  Обращение к полям прочитанной строки производится с помощью одного из индексаторов DbDataReader.

·  В процессе чтения данных с помощью DbDataReader соединение недоступно другим пользователям (оно занято), поэтому важно закрывать DbDataReader сразу после завершения обработки.

Покажем, как использовать метод Read для чтения данных таблицы Studs.

·  Cделайте копию текущего решения, переименуйте его (а также вложенный в него проект) в OleDbCommand,

·  Внесите изменения в класс MainForm, как показано ниже.

public partial class MainForm : Form

{

  string dbPath;

  OleDbConnection cn;

  public MainForm()

  {

   InitializeComponent();

   bn.ItemClicked += new ToolStripItemClickedEventHandler(bn_ItemClicked);

  }

  void MainForm_Load(object sender, EventArgs e)

  {

   try

   {

    cn = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0; Data Source=" +

      FindAFile("\\Students.mdb"));

    ConnectAndRead();

   }

   catch (Exception ex)

   {

    MessageBox.Show(ex.Message, Text);

    Application.Exit();

    return;

   }

  }

string FindAFile(string file)

  {

   dbPath = Environment.CurrentDirectory;

   string root = Path.GetPathRoot(dbPath);

   while (true)

   {

    string data = dbPath + "\\Data",

      path = data + file;

    if (Directory.Exists(data) && File.Exists(path))

      return path;

    path = dbPath + file;

    if (File.Exists(path))

      return path;

    if ((dbPath = Path.GetDirectoryName(dbPath)) == root)

      throw new FileNotFoundException("Could not find Database file: " + file);

   }

  }

  void ConnectAndRead()

  {

   cn.Open();

   IDbCommand cmd = cn.CreateCommand();

   cmd.CommandText = "SELECT * FROM Studs";

   IDataReader reader = cmd.ExecuteReader();