Опубликован: 05.08.2010 | Доступ: свободный | Студентов: 2008 / 45 | Оценка: 4.50 / 4.40 | Длительность: 60:26:00
Самостоятельная работа 5:

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

Упражнение 7. Работа с объектом DataView

Объект DataView выполняет представление одних и тех же данных загруженной таблицы БД в нескольких разных форматах по принципу "Один документ - много представлений". DataView работает только с таблицей DataTable и готовит для отображения все ее столбцы без исключения. В присоединенном к таблице объекте DataView данные можно сортировать или задавать некоторые условия выборки строк представляемой таблицы. DataView физически не включает в себя данные отображаемой таблицы, он только изменяет их представление в элементе отображения "на лету".

Можно для одной таблицы заготовить несколько объектов DataView, каждый со своими настройками, и поочередно связывать их с элементом отображения. При этом в памяти компьютера будет находиться только одна копия данных, что существенно экономит ресурсы. Сам экземпляр объекта DataView можно настроить так, чтобы он запрещал редактирование данных связанной с ним таблицы, хотя в другом объекте такие ограничения на ту же самую таблицу могут отсутствовать. Операцию вставки, обновления или удаления данных в связанной таблице разрешают (запрещают) через свойства AllowNew, AllowEdit, AllowDelete. Если флаг AllowNew разрешает вставку, то новая строка добавляется в DataView методом AddNew().

При заполнении таблицы DataTable программно или данными БД строки отображаются в том порядке, в котором они были вставлены в таблицу или извлечены из БД. С любой таблицей уже связан один объект DataView, ссылка на который носит имя свойства DefaultView только для чтения. Через этот объект-представление мы можем сортировать представление данных таблицы и связывать элемент отображения не с самой таблицей, а с ее отсортированным представлением - объектом DefaultView.

Если встроенного представления нам мало, можно создать и настроить еще ряд объектов DataView и по мере надобности подключать их к свойству DataSource элемента отображения данных. Связанную с элементом отображения таблицу сортировать нельзя, как и сам связанный с таблицей элемент отображения. Но если между таблицей и элементом отображения имеется посредник DataView, то фильтрацию и сортировку отображаемых данных исходной таблицы можно выполнять через него.

У каждого элемента DataRow есть свойство RowState, в котором ведется история состояния строки при ее редактировании. Это свойство автоматически принимает одно из значений перечисления DataRowState при выполнении действий над строкой:

  • Detached - строка только что создана методом DataTable.NewRow(), но еще не добавлена в таблицу методом DataTable.Rows.Add()
  • Added - строка добавлена в коллекцию таблицы, но не помечена как окончательно принятая один из методов: DataRow.AcceptChanges(), DataTable.AcceptChanges(), DataSet.AcceptChanges()
  • Deleted - строка помечена как удаленная из таблицы методом DataRow.Delete(), но не принята окончательно методом AcceptChanges()
  • Modified - строка была изменена, но еще не принята
  • Unchanged - строка не изменилась со времени последнего вызова AcceptChanges()

Объектная модель таблицы хранит несколько версий одной и той же строки. Эти версии строки зависят от того, применялся или нет к ней метод AcceptChanges(). Значения версий определяются перечислением DataRowVersion и могут иметь значения: Current, Default, Original, Proposed. Какие версии имеет строка, можно проверить с помощью ее метода DataRow.HasVersion(DataRowVersion), например, следующий код распечатает все существующие версии указанной строки

void CheckVersion(DataRow row)
        {
            if (row.HasVersion(DataRowVersion.Current))
                Console.WriteLine("Версия Current");
            if (row.HasVersion(DataRowVersion.Default))
                Console.WriteLine("Версия Default");
            if (row.HasVersion(DataRowVersion.Original))
                Console.WriteLine("Версия Original");
            if (row.HasVersion(DataRowVersion.Proposed))
                Console.WriteLine("Версия Proposed");
        }

Указанные версии строки связаны с ее редактированием и вызовом метода AcceptChanges() объектов DataRow, DataTable или DataSet следующим образом:

  1. После вызова метода DataRow.BeginEdit(), если значение строки будет изменено, станут доступными версии Current и Proposed (текущий и предложенный)
  2. После вызова метода DataRow.CancelEdit() будет удалена версия Proposed
  3. После вызова метода DataRow.EndEdit() версия Proposed становится версией Current
  4. После вызова метода DataRow.AcceptChanges() версия Proposed становится версией Current ; версия Original не изменяется
  5. После вызова метода DataTable.AcceptChanges() версия Original становится идентичной версии Current
  6. После вызова метода DataTable.RejectChanges() (- отклонить изменения) версия Original становится версией Current

Объект DataView имеет свойства, позволяющие управлять представляемыми данными:

  • RowFilter - позволяет задать критерий выбора представляемых строк, например
    RowFilter="Price < 10"; 
      RowFilter="LastName LIKE ' W%' "; 
      RowFilter="ProductID = 1"
  • RowStateFilter - позволяет выбирать строки, находящиеся в определенном состоянии. Значение этого свойства определяется перечислением System.Data.DataViewRowState:
    • Added - новые строки
    • CurrentRows - текущие строки, включая неизмененные, новые и модифицированные
    • Deleted - строки, помеченные как удаленные
    • ModifiedCurrent - ближайшая модифицированная версия данных, полученная из ModifiedOriginal
    • ModifiedOriginal - предыдущая версия данных, из которой получена версия ModifiedCurrent
    • None - пустое значение
    • OriginalRows - первоначальные строки, загруженные из БД
    • Unchanged - строка не менялась

Например, следующая функция настраивает DataView на представление строк таблицы предыдущего или следующего состояния модификации

DataView ViewChanges(DataTable table, bool viewCurrent)
        {
            DataView view = table.DefaultView;
    
            if (viewCurrent == true)
                view.RowStateFilter = DataViewRowState.ModifiedCurrent;
            else
                view.RowStateFilter = DataViewRowState.ModifiedOriginal;
    
            return view;
        }
  • Sort - это свойство указывает порядок сортировки представляемых данных, например Sort="FullName ASC" ; Sort="FullName DESC" ; - сортируют в прямом и обратном порядке представление таблицы по полю FullName

Объект DataView имеет два метода поиска данных для выборки в представление, оба из которых осуществляют поиск в отсортированном (в свойстве Sort ) столбце по заданному критерию:

  • DataView.Find() - ищет первое вхождение строки в DataView и возвращает номер строки, или -1
  • DataView.FindRows() - ищет массив строк и возвращает его, или пустой массив

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

  • Добавьте в решение новый проект с именем WinForms7 и оформите интерфейс пользователя в соответствии с таблицей
Объект Свойство Значение Пояснения
Form Text Упражнение 7 Заголовок окна
  MaximizeBox False Запретить системную кнопку
Panel Dock Top Верхний контейнер для Label и ComboBox
Panel Dock Fill Нижний контейнер для DataGrid
Label Text Letter: Объекты Label и ComboBox поместите в верхний контейнер Panel
ComboBox (Name) cbLetters Для размещения букв латинского алфавита
  FlatStyle Flat Плоский стиль элемента
Label Text Column:  
ComboBox (Name) cbColumns Для размещения имен столбцов
DataGrid (Name) dataGrid Объект DataGrid поместите в нижний контейнер Panel
  AllowSorting False Запретить сортировку столбцов через DataGrid
  CaptionText Представления таблицы Customers Заголовок DataGrid
  Dock Fill Развернуть на весь контейнер Panel
  ReadOnly True Запретить редактирование данных
  • Модифицируйте файл Form1.cs следующим образом
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
    
// Дополнительные пространства имен
using System.Data.OleDb;
using System.Data.Common;
    
namespace WinForms7
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
    
            // Подписка на события ComboBox общего обработчика
            cbLetters.SelectedIndexChanged += Combo_SelectedIndexChanged;
            cbColumns.SelectedIndexChanged += Combo_SelectedIndexChanged;
    
            // Загрузки объектов данными
            LoadCustomers();
            LoadLetters();
            LoadColumns();// Вызывать после загрузки данных LoadCustomers()
        }
    
        // Строка соединения к БД с абсолютным путем, определяемым сборкой
        String ConnectionString()
        {
            // Используем построитель строки подключения 
            OleDbConnectionStringBuilder objConnectionStringBuilder =
                new OleDbConnectionStringBuilder();
            objConnectionStringBuilder.Provider = "Microsoft.Jet.OLEDB.4.0";
            objConnectionStringBuilder.DataSource =
                Application.StartupPath.ToString() + @"\Data\Northwind.mdb";
    
            return objConnectionStringBuilder.ToString();
        }
    
        DataTable tableCustomers;// Поле, видимое в методах
        void LoadCustomers()
        {
            // Формируем поставщик 
            OleDbCommand selectCommand = new OleDbCommand();
            selectCommand.CommandText =
                "SELECT * FROM Customers";// Будем читать все столбцы
            selectCommand.Connection = new OleDbConnection(ConnectionString());
            selectCommand.CommandType = CommandType.Text;// По умолчанию
            OleDbDataAdapter adapter = new OleDbDataAdapter(selectCommand);
    
            // Создаем объект таблицы
            tableCustomers = new DataTable();
    
            // Заполняем таблицу
            adapter.Fill(tableCustomers);
            // Адресуемся к встроенному в таблицу представлению
            DataView defaultView = tableCustomers.DefaultView;
    
            // Связываем встроенное представление с элементом отображения
            dataGrid.DataSource = defaultView;
        }
    
        void LoadLetters()
        {
            // Добавили первый элемент списка
            cbLetters.Items.Add("All");
    
            // Дополняем список буквами алфавита
            for (char ch = 'A'; ch <= 'Z'; ch++)
            {
                cbLetters.Items.Add(ch);
            }
    
            // Устанавливаем на первый индекс 
            cbLetters.SelectedIndex = 0;
        }
    
        void LoadColumns()
        {
            // Создаем временную таблицу для имен столбцов
            DataTable tableTmp = new DataTable();
            // Добавляем один столбец для хранения имен столбцов 
            tableTmp.Columns.Add("ColumnName", typeof(String));
            // Заполняем временную таблицу именами столбцов исходной таблицы
            for (int i = 0; i < tableCustomers.Columns.Count; i++)
            {
                tableTmp.Rows.Add(tableCustomers.Columns[i].ColumnName);
            }
            // Создаем представление по единственному столбцу
            DataView view = new DataView(tableTmp);
    
            // Связываем представление с элементом отображения
            cbColumns.DataSource = view;
            cbColumns.DisplayMember = "ColumnName";
    
            // Ищем нужное имя и позиционируем список
            view.Sort = "ColumnName";// Сортируем для списка имен столбцов
            int selectedIndex = view.Find("CustomerID");// По отсортированному можно
            cbColumns.SelectedIndex = selectedIndex;// Позиционируем программно на CustomerID
        }
    
        private void Combo_SelectedIndexChanged(object sender, EventArgs e)
        {
            // Еще не созданы
            if (cbLetters == null || cbColumns == null)
                return;
            // Еще ничего не выбрано
            if (cbLetters.SelectedIndex == -1 || cbColumns.SelectedIndex == -1)
                return;
    
            // Извлекаем символ из cbLetters
            String letter = cbLetters.SelectedItem.ToString();
            if (letter == "All")
                letter = String.Empty;
    
            // Извлекаем из cbColumns, связанного с DataView, выбранное имя столбца 
            Object obj = cbColumns.SelectedItem;
            String columnName = ((DataRowView)obj).Row["ColumnName"].ToString();
    
            // Создаем для таблицы Customers объект представления и настраиваем его
            DataView view = new DataView(tableCustomers);
            view.RowFilter = "CustomerID LIKE '" + letter + "%'";
            view.Sort = columnName;
    
            // Связываем настроенное представление с объектом отображения
            dataGrid.DataSource = view;
        }
    }
}
  • Запустите приложение и проверьте его функциональность



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

При выполнении в лабораторной работе упражнения №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" или один из зависимых от них компонентов. Не удается найти указанный файл.

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