Опубликован: 05.08.2010 | Уровень: специалист | Доступ: платный
Самостоятельная работа 5:

Просмотр данных OLE DB средствами ADO.NET

Упражнение 4. Поиск строки DataTable с помощью метода Find()

Объект DataTable - это находящееся в кэше памяти представление выбранных из БД данных в табличной форме. Он может быть заполнен объединением одной или нескольких таблиц из базы данных. Первоначальное заполнение DataTable выполняется адаптером в соответствии с SQL-запросом. Но после первоначальной загрузки некоторые столбцы могут быть добавлены в DataTable уже как результат вычислительных действий над исходными столбцами в отсоединенном режиме.

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

Есть два пути выборки нескольких строк или поиска конкретной строки таблицы: либо сформировать SQL-запрос к исходной таблице БД с заданным условием, либо загрузить исходную таблицу в кэш и уже в нем выполнять требуемую выборку. Объект DataTable имеет встроенные средства выборки нескольких строк из таблицы кэша с их сортировкой или поиска конкретной строки. В последнем случае применяется метод Find(), который работает только со столбцом, содержащим значения первичного ключа. Поэтому перед вызовом метода Find() нужно либо загрузить схему, либо вручную указать первичный ключ. Результатом выборки будет новая таблица, строка или массив строк.

В данном упражнении мы будем работать с таблицей Customers, схема которой показана на рисунке


SQL-командой мы полностью загрузим в кэш все столбцы таблицы Customers. В отсоединенном режиме по выбранному CustomerID будем искать соответствующую запись и показывать пользователю значения полей CustomerID, CompanyName, Adress, City, Region и Phone виртуальной таблицы. Столбцы CustomerID и CompanyName динамически свяжем с раскрывающимся списком ComboBox, причем столбец CompanyName сделаем видимым. Значения полей найденной записи будем отображать в элементах TextBox, недоступных для редактирования. Столбцу CustomerID присвоим статус первичного ключа виртуальной таблицы.

  • Добавьте к решению новый проект оконного приложения с именем WinForms4, назначьте его стартовым и создайте пользовательский интерфейс в соответствии с таблицей
Объект Свойство Значение Пояснения
Form1 Text Упражнение 4 Заголовок окна
  MaximizeBox False Отключили системную кнопку
  FormBorderStyle FixedSingle Размеры окна менять нельзя
Label Text Customer:  
ComboBox (Name) cbCustomers  
  DropDownStyle DropDownList Текст в поле списка редактировать нельзя
Label Text Customer ID:  
TextBox (Name) txtCustomerID  
Label Text Company Name:  
TextBox (Name) txtCompanyName  
Label Text Address:  
TextBox (Name) txtAddress  
Label Text City:  
TextBox (Name) txtCity  
Label Text Region:  
TextBox (Name) txtRegion  
Label Text Phone:  
TextBox (Name) txtPhone  
txtCustomerID, txtCompanyName, txtAddress, txtCity, txtRegion, txtPhone BorderStyle FixedSingle Простая рамка вокруг текстового поля

Форма на этапе проектирования должна выглядеть так


  • Защитите текстовые поля от редактирования, для этого: выделите на форме все элементы TextBox и в панели Properties в режиме Events создайте для них общий обработчик события KeyPress, затем общий обработчик события KeyDown. Обработчики заполните так
private void txtCustomerID_KeyPress(object sender, KeyPressEventArgs e)
        {
            e.Handled = true;
        }
    
        private void txtCustomerID_KeyDown(object sender, KeyEventArgs e)
        {
            e.Handled = true;
        }
  • В панели Solution Explorer добавьте к корневому узлу проекта WinForms4 папку Data и перетащите в нее мышью из соседнего проекта файл Northwind.mdb (при этом отклоните предложение мастера конфигурации источника данных)
  • Добавьте в начало файла Form1.cs подключения пространства имен сборки System.Data.dll, нужные для обеспечения видимости библиотечных классов
// Дополнительные пространства имен
using System.Data.OleDb;
using System.Data.Common;
using System.Collections;
  • Добавьте в класс Form1 метод LoadCustomers(), который загружает таблицу Customers из БД с помощью динамически созданного поставщика данных и SQL-запроса
// Строка соединения с абсолютным путем к БД, определяемым сборкой
        String ConnectionString(String fileName)
        {
            string JetEngineString = @"Provider=Microsoft.Jet.OLEDB.4.0;"
                + "Jet OLEDB:Engine Type=5;Data Source=";
            string pathToFile = Application.StartupPath.ToString() + "\\Data\\";
            return JetEngineString + pathToFile + fileName.Trim() + ".mdb";
        }
    
        DataTable tableCustomers;
        void LoadCustomers()
        {
            OleDbCommand selectCommand = new OleDbCommand();
            selectCommand.CommandText="SELECT * FROM Customers";
            selectCommand.Connection = new OleDbConnection(ConnectionString("Northwind"));
            selectCommand.CommandType = CommandType.Text;
            OleDbDataAdapter adapter = new OleDbDataAdapter(selectCommand);
    
            tableCustomers = new DataTable();// Создать таблицу
            try
            {
                // Заполнить таблицу
                adapter.Fill(tableCustomers);
                // Указать первичный ключ из одного столбца для использования метода Find()
                tableCustomers.PrimaryKey = 
                    new DataColumn[] { tableCustomers.Columns["CustomerID"] };
            }
            catch (OleDbException exc)
            {
                tableCustomers = null;
                MessageBox.Show(exc.Message, "Ошибка",
                    MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            finally
            {
                selectCommand.Connection.Close();
            }
    
            // Связываем ComboBox с виртуальной таблицей
            cbCustomers.DataSource = tableCustomers;
            cbCustomers.DisplayMember = "CompanyName";
            cbCustomers.ValueMember = "CustomerID";
        }
  • Вставьте вызов метода LoadCustomers() в конструктор класса Form1 проекта WinForms4
public Form1()
        {
            InitializeComponent();
    
            LoadCustomers();
        }
  • Выделите объект cbCustomers и создайте для его события SelectedIndexChanged обработчик. Этот же обработчик зарегистрируйте и для события BindingContextChanged объекта cbCustomers. Заполните обработчик следующим кодом
private void cbCustomers_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (tableCustomers == null)
                return; // При исключении выходить
    
            // Найти запись
            Object findValue = cbCustomers.SelectedValue;// Выделенное значение ValueMember
            DataRow row = tableCustomers.Rows.Find(findValue);
    
            // Заполнить текстовые поля
            if (row != null)
            {
                txtCustomerID.Text = row["CustomerID"].ToString();
                txtCompanyName.Text = row["CompanyName"].ToString();
                txtAddress.Text = row["Address"].ToString();
                txtCity.Text = row["City"].ToString();
                txtRegion.Text = row["Region"].ToString();
                txtPhone.Text = row["Phone"].ToString();
            }
        }
  • Запустите проект: список заполняется сразу при запуске проекта, текстовые поля отображают подробности при выборе заказчика и недоступны для редактирования, как и поле ComboBox


Поиск строки в виртуальной таблице DataTable выполняется методом Find() по столбцу CustomerID, назначенному нами первичным ключем. Без этого метод работать не будет. Критерий поиска берется из выбранного пользователем значения списка. Задача решена.

Алексей Бабушкин
Алексей Бабушкин

При выполнении в лабораторной работе упражнения №1 , а именно при выполнении нижеследующего кода:

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Text;

using System.Windows.Forms;

using Microsoft.Xna.Framework.Graphics;

   

namespace Application1

{

    public partial class MainForm : Form

    {

        // Объявим поле графического устройства для видимости в методах

        GraphicsDevice device;

   

        public MainForm()

        {

            InitializeComponent();

   

            // Подпишемся на событие Load формы

            this.Load += new EventHandler(MainForm_Load);

   

            // Попишемся на событие FormClosed формы

            this.FormClosed += new FormClosedEventHandler(MainForm_FormClosed);

        }

   

        void MainForm_FormClosed(object sender, FormClosedEventArgs e)

        {

            //  Удаляем (освобождаем) устройство

            device.Dispose();

            // На всякий случай присваиваем ссылке на устройство значение null

            device = null;       

        }

   

        void MainForm_Load(object sender, EventArgs e)

        {

            // Создаем объект представления для настройки графического устройства

            PresentationParameters presentParams = new PresentationParameters();

            // Настраиваем объект представления через его свойства

            presentParams.IsFullScreen = false; // Включаем оконный режим

            presentParams.BackBufferCount = 1;  // Включаем задний буфер

                                                // для двойной буферизации

            // Переключение переднего и заднего буферов

            // должно осуществляться с максимальной эффективностью

            presentParams.SwapEffect = SwapEffect.Discard;

            // Устанавливаем размеры заднего буфера по клиентской области окна формы

            presentParams.BackBufferWidth = this.ClientSize.Width;

            presentParams.BackBufferHeight = this.ClientSize.Height;

   

            // Создадим графическое устройство с заданными настройками

            device = new GraphicsDevice(GraphicsAdapter.DefaultAdapter, DeviceType.Hardware,

                this.Handle, presentParams);

        }

   

        protected override void OnPaint(PaintEventArgs e)

        {

            device.Clear(Microsoft.Xna.Framework.Graphics.Color.CornflowerBlue);

   

            base.OnPaint(e);

        }

    }

}

Выбрасывается исключение:

Невозможно загрузить файл или сборку "Microsoft.Xna.Framework, Version=3.0.0.0, Culture=neutral, PublicKeyToken=6d5c3888ef60e27d" или один из зависимых от них компонентов. Не удается найти указанный файл.

Делаю все пунктуально. В чем может быть проблема?

Иван Циферблат
Иван Циферблат
Россия, Таганрог, 36, 2000