- •Упражнение 1. Просмотр таблицы с помощью объектов DbCommand и DbDataReader
- •Упражнение 2. Выборочный просмотр таблицы с помощью объектов DbCommand и DbDataReader
- •Упражнение 3. Выборка данных с помощью объекта DataTable
- •Упражнение 4. Поиск строки DataTable с помощью метода Find()
- •Упражнение 5. Выборка строк DataTable с помощью метода Select()
- •Упражнение 6. Вычисляемые столбцы объектов DataTable
- •Упражнение 7. Работа с объектом DataView
Упражнение 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 следующим образом:
После вызова метода DataRow.BeginEdit(), если значение строки будет изменено, станут доступными версии Current иProposed (текущий и предложенный)
После вызова метода DataRow.CancelEdit() будет удалена версия Proposed
После вызова метода DataRow.EndEdit() версия Proposed становится версией Current
После вызова метода DataRow.AcceptChanges() версия Proposed становится версией Current ; версия Original не изменяется
После вызова метода DataTable.AcceptChanges() версия Original становится идентичной версии Current
После вызова метода 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;
}
}
}
Запустите приложение и проверьте его функциональность
