Лекция № 10
Тема: «Работа с базами данных»
План
1. Создание соединения с базой данных
2. Работа с таблицей базы данных
3. Создание форм для работы с данными БД
4. Методы и свойства для работы с данными в таблице
1. Создание соединения с базой данных
Тип СУБД, которую Вы можете подключить к проекту C# зависит от версии Visual Studio. Если используется бесплатная версия Express Edition, то работать можно будет только с локальными версиями СУБД Access, SQL Server Compact, отдельными файлами СУБД SQL Server. Если нужно работать с клиент/серверными СУБД, то нужно использовать Visual Studio Professional.
При подключение разных СУБД отличие будет только в особенностях настройки подключения к самой БД. Принципы отображения данных на форме и работы с ними абсолютно одинаковы и не зависят от типа БД. Так как мы работаем в Visual Studio Express, то будем рассматривать все примеры с использованием СУБД Access. Если нужно будет перейти на клиент/серверную СУБД, то создайте БД с одноименными таблицами и полями и настройте подключение к ней. Далее весь код будет работать без изменений.
Для корректной работы с БД необходимо при проектировании данных выполнить ряд условий:
- названия всех объектов (БД, таблиц, полей, индексов, ограничений и т.п.) выполнять только латинскими буквами;
- каждая таблица должна иметь ключевое поле (желательно поле-счетчик).
Настройка доступа к БД
Текущее подключение к БД отображается с специальной панели "Источники данных". Если панель не отображается, то выполните команду меню "Данные - Показать источники данных".

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

Появится окно для настройки соединения с БД. С помощью кнопки "Изменить"

В новом окне укажите формат СУБД Microsoft Access.

В новом окне укажите путь к БД.

Если БД защищена паролем, то с помощью кнопки "Дополнительно" можно указать пароль доступа к БД в строке "Jet OLEDB:Database Password" пароль доступа к БД.

После задания всех параметров в окне мастера можно раскрыть элемент "Строка подключения" для просмотра параметров подключения к БД. Если Вы задали пароль для доступа к БД, то станут доступны два переключателя. Первый предлагает не добавлять пароль в строку подключения. Второй предлагает добавить пароль в строку подключения.
Если указать первый переключатель, то данные из БД по умолчанию отображаться не будут, пока Вы программно не добавите к строке подключения пароль доступа.

Если указать второй переключатель, то пароль будет добавлен в строку подключения и никаких дополнительных команд в коде не понадобится. Однако, строка подключения - это один из параметров работы приложения. Необходимо напомнить, что параметры приложения хранятся на диске в файле user.config. Следовательно существует возможность найти этот файл на диске и прочитать пароль доступа, что небезопасно.

Поэтому рекомендуется выбирать первый переключатель для защиты пароля.
После задания нужных параметров и нажатия на кнопку "Далее" появится диалоговое окно вида:

В этом окне Вам предлагается скопировать файл БД в папку с проектом. Подтвердите операцию.
Замечание! После подтверждения операции все дальнейшие изменения в БД нужно выполнять в той копии, которая находится в папке с проектом.
На следующем шаге мастера предлагается сохранить строку подключения в файл конфигурации. Если подтвердить эту операцию, то строка будет записана в файл user.config под именем, заданным в текстовом поле. Если не сохранять пароль доступа, то сохранение можно подтвердить. Если отказаться от сохранения строки подключения, то она будет "встроена" в исполняемый файл проекта, что значительно повышает уровень защиты БД.

На следующем шаге укажите таблицы БД для подключения к проекту и нажмите кнопку "Готово".

В результате в панели "Источники данных" отобразится созданное подключение с перечнем подключенных таблиц и полей в них.

Кроме этого в структуре проекта появится новый элемент с расширением *.xsd

Изменение параметров подключения
Если Вам нужно добавить дополнительную таблицу в проект, то в панели "Источники данных" щелкните на кнопке "Настроить источник данных с помощью мастера". Откроется окно, в котором можно отметить нужные таблицы. Никаких других параметров подключения настроить нельзя.
Если нужно заново указать параметры подключения: новый путь к БД, пароль доступа и др., то нужно удалить файл *.xsd из проекта (тем самым будет удалено старое подключение) и создать подключение с помощью мастера заново.
2. Работа с таблицей базы данных
Для работы с таблицами на панели "Источник данных" щелкните на кнопке "Изменить набор данных в конструкторе". Откроется окно со структурой таблиц и связями между ними.

Каждое поле таблицы имеет свойства:
|
Свойство |
Описание |
|
Name |
Имя компонента для обращения к нему в коде |
| AllowDBNull | Указывает, можно ли оставлять поле не заполненным |
| AutoIncrement | Указывает, что поле является счетчиком |
| AutoIncrementSeed | Задает начальное значение для поля-счетчика |
| AutoIncrementStep | Задает шаг изменения поля-счетчика |
| DataType | Задает тип поля в таблице |
| DefaultValue | Задает значение по умолчанию для поля в новой записи |
| Expression | Задает формулу для вычисления значения поля |
| MaxLength | Задает максимальную длину поля в символах |
| ReadOnly | Блокирует поле для ввода |
| Source | Задает имя поля таблиц БД |
| Unique | Задает признак уникальности значений в поле. Если включен, то ввести одинаковые значение будет невозможно |
Если в таблице имеется ключевое поле-счетчик, то для него обязательно задайте свойства: AutoIncrementSeed = 1; AutoIncrementStep = 1
Если в таблицу БД было введено новое поле после создания подключения, то вызовите контекстное меню нужной таблицы, выберите команду "Настроить". Откроется окно с текстом запроса к таблице. В список полей добавьте через запятую новое поле.
Если в таблице БД було удалено поле после создания подключения, то щелкните слева от имени удаленного поля для его выделения и нажмите клавишу Delete.
Создание вычисляемых полей
Можно создавать вычисляемые поля: поля, которых физически нет в таблице БД, но их значение автоматически рассчитываются на основании данных из других полей.
Для создания такого поля в контекстном меню таблицы выберите команду ""Добавить - Столбец". В свойстве Name задайте имя поля, а в свойстве Expression введите формулу для расчета поля.
Пример: Пусть в таблице есть поле srbal для хранения среднего балла студента. Вычисляемое поле «стипендия» (stip) нужно рассчитать по формуле: средний балл * 50. При этом стипендию получают только студенты со средним баллом от 4 и выше.
Добавим новое поле, зададим ему имя stip и в свойстве Expression введем формулу вида:
iif (srbal>=4, srbal*50, 0)
Усложним пример. Стипендия рассчитывается по формуле: 1450, если средний балл 5; 1300, если средний балл выше 4; 0 - в противном случае.
В свойстве Expression нового поля введем формулу вида:
iif(srbal==5, 1450, iif(srbal==4, 1300 ,0))
Изменение команд обновления данных в таблицах
Мастер создания подключения к БД автоматически генерирует команды для добавления, обновления, удаления и просмотра данных из таблиц. Если выделить TableAdapter нужной таблицы, то в свойствах DeleteCommand, InsertCommand, SelectCommand, UpdateCommand можно увидеть эти команды. Эти команды часто срабатывают с ошибкой, когда после добавления новой записи нужно ее сразу удалить.
Для решения проблемы, код этих команд нужно изменить. Для этого щелкните правой кнопкой на нужном TableAdapter, выберите команду "Настроить", щелкните на кнопке "Дополнительно" и в открывшемся окне снимите флажок "Использовать оптимистическую блокировку", щелкните ОК, а затем Готово.

3. Создание форм для работы с данными БД
Отображение данных из таблиц БД на форме можно выполнять или с помощью сетки (табличная форма) или с помощью отдельных компонентов (страничная форма).
Создание табличных форм
На табличных формах пользователь видит сразу множество записей таблицы БД. Если данные еще и отсортированы по нужному полю, то поиск нужной записи значительно облегчается и переход на нужную запись значительно ускоряется.
Для создания табличных форм используется компонент DataGridView. После его добавления на форму появляется окно для указания источника данных (таблицы).

После указания нужной таблицы, в сетке отобразятся колонки, соответствующие полям таблицы, а под формой появится 3 новых невидимых компонента. DataSet - компонент, ссылающийся на источник данных (БД), TableAdapter - компонент, в который загружается информация из таблицы, BindingSource - конвертер данных таблицы в универсальный формат C# для дальнейшей работы с данными.
Имена этих компонентов по умолчанию будут начинаться с имени связанной таблицы. Например, если выбрать для сетки DataGridView таблицу sotr, то компоненты будут иметь имена, показанные на рисунке.

Замечание. Имя компонента DataSet обычно начинается не с имени таблицы, а с имени БД. В данном примере БД имеет имя sotr.mdb. Так как имя БД совпало с именем таблицы, то и начало имен компонентов совпадает. На самом деле, если бы имя БД, например, было dbase.mdb, то компоненты имели бы имена: dbaseDataSet (по имени БД), sotrBindingSource, sotrTableAdapter (по имени таблицы). Программа готова к запуску и отображению данных из таблицы на форме.
Компонент BindingSource связывается с таблицей с помощью свойств: DataSource - указывается ссылка на DataSet, DataMember - имя таблицы. Именно через него будут выполняться все операции по чтению и редактированию данных.
Если нужно подключить еще одну таблицу, то нанесите новую сетку, и укажите для нее новую таблицу. В результате под формой появится два новых компонента BindingSource и TableAdapter. Таким образом, каждая подключенная таблица будет представлена на форме этими двумя компонентами, имена которых, по-умолчанию, будут начинаться с имени таблицы.
Если Вам нужно подключить таблицу для работы, но не нужно отображать ее виде сетки на форме, выполните подключение через сетку, а затем сетку удалите. Пара компонентов BindingSource и TableAdapter останутся на форме и таблица останется подключенной.
Так как при проектировании таблиц БД имена полей записываются латинскими буквами, то и в сетке заголовки колонок отображаются в исходном виде. Для удобства пользователя необходимо переименовывать колонки сетки. Для этого откройте свойство Columns сетки. В новом окне можно выделить колонку и в ее свойстве HeaderText ввести нужное название. Также можно скрыть ненужные колонки с помощью свойства Visible=false.
Иногда, возникает ситуация, при которой пользователь добавляет новые поля в таблицу после ее подключения на форме. В этом случае новые поля не отображаются в сетке. Для решения проблемы для компонента BindingSource задайте свойство DataMember = отсутствует, а затем DataMember = имя таблицы. Структура таблицы будет прочитана заново и все колонки отобразятся корректно. При этом все настройки колонок (переименования, скрытие и т.д.) будут сброшены в начальное состояние.
Если открыть обработчик события Load формы, то там будет находится автоматически сгенерированная команда вида:
this.sotrTableAdapter.Fill(this.sotrDataSet.sotr);
Данная команда загружает содержимое таблицы sotr в компонент sotrTableAdapter для дальнейшей работы. Если эту команду удалить, то на форме будет отображаться пустая сетка, так как данные из БД не загружены.
Если Вы подключаете несколько таблиц, то такая команда будет сгенерирована для каждой из них. Например:
//загружаем таблицу sotr
this.sotrTableAdapter.Fill(this.sotrDataSet.sotr);
//загружаем таблицу dolg
this.dolgTableAdapter.Fill(this.sotrDataSet.dolg);
Иногда при проектировании формы и отладке программы в событии Load может автоматически сгенерироваться несколько одинаковых команд загрузки данных из БД. В этом случае удаляйте все копии, оставляя только одну из них.
Подстановка пароля БД к строке подключения
При настройке подключения к БД с помощью мастера для защиты доступа к БД было сказано, что пароль доступа желательно не добавлять в строку подключения, а указывать в коде программы.
Если база защищена паролем, то запустив приложение, Вы увидите, что данные в сетке не отображаются. Это связано с тем, что пароль к БД не указан и подключение не выполняется.
Для решения проблемы необходимо в событии Load формы перед командами загрузки таблиц (Fill) добавить код настройки строки подключения. При этом у нас может быть два случая:
- строка подключения с целью повышения безопасности не сохранена в файл конфигурации приложения
В этом случае строка подключения указывается непосредственно для компонента TableAdapter таблицы с помощью команды:
TableAdapter.Connection.ConnectionString+=";Jet OLEDB:Database Password=пароль";
Например, для нашего примера, код может иметь вид:
sotrTableAdapter.Connection.ConnectionString+=";Jet OLEDB:Database Password=пароль";
Если подключается несколько таблиц, то TableAdapter для каждой таблицы. Например, в нашем примере было две таблицы, значит команда может иметь вид:
sotrTableAdapter.Connection.ConnectionString=dolgTableAdapter.Connection.ConnectionString+=";Jet OLEDB:Database Password=пароль";
- строка подключения сохранена в файл конфигурации приложения
В этом случае Вы должны помнить имя, под которым строка подключения была сохранена. Если не помните, откройте файл app.config, найдите раздел connectionStrings и прочитайте параметр name.
Чаще всего строка ConnectionString имеет имя, начинающееся на имя БД. Например, в нашем случае для БД с именем sotr.mdb строка подключения будет сохранена под именем sotrConnectionString.
Команда настройки строки подключения может иметь вид:
Properties.Settings.Default["sotrConnectionString"]+=";Jet OLEDB:Database Password=пароль";
Независимо от того, сколько таблиц будет подключено в проекте, настройка строки подключения выполняется один раз для всех таблиц.
Обращение к значению нужного поля
Часто при написании кода программы нужно обратиться к значению конкретного поля текущей записи таблицы. Это значение может использоваться в расчетах, его можно проверить с помощью условия и т.п.
Для обращения к полю таблицы используется компонент BindingSource и его свойство Current.
Например. Пусть имеется компонент sotrBindingSource. Необходимо прочитать значение поля fam текущей записи. Для этого используют команду вида:
(sotrBindingSource.Current as DataRowView)["fam"]
Замечание. Обращение к любому полю таблицы возвращает значение в универсальном формате object. Поэтому для дальнейшего использования значения поля в коде его нужно конвертировать в нужный тип с помощью метода ToString() или класса Convert.
Например. Выведем в окне сообщения фамилию (fam) текущей записи.
MessageBox.Show((sotrBindingSource.Current as DataRowView)["fam"].ToString());
Еще пример. Оклад (oklad) текущего сотрудника увеличи в 2 раза и выведем его в текстовом поле textBox1.
textBox1.Text=(Convert.ToDouble((sotrBindingSource.Current as DataRowView)["oklad"])*2).ToString();
Ограничения значения поля
Для полей можно проверять условия на значения. Это позволит защитить программу от ввода недопустимых данных. Такую защиту можно задать на этапе проектирования БД. Но мы рассмотрим способ защиты на уровне приложения.
Задавать ограничение при вводе можно для самой сетки, в которой отображается таблица БД.
Пример. Пусть в таблице есть поле oklad, которое отображается в 6 колонке сетки.. Нужно запретить вводить не числовые значения, а также значения меньше 0. При этом, если пользователь не знает значение оклада, то может ввести 0, чтобы пропустить это поле.
В событии CellValidationg сетки DataGridView введите код:
private void dataGridView1_CellValidating(object sender, DataGridViewCellValidatingEventArgs e)
{
//для обращения к значению текущей ячейки событие имеет параметр e.FormattedValue
//для определения номера текущей колонки событие имеет параметр e.ColumnIndex
//если текущая колонка не 6 (нумерация с 0) или в ячейке введен 0
//то код проверки не выполняется
if (e.ColumnIndex != 5 || e.FormattedValue.ToString() == "0") return;
//переменная для конвертирования текста в число
double rez;
//если ячейка не конвертируется в число (!double.TryParse)
//или конвертируется, но полученное значение <0
if (!double.TryParse(e.FormattedValue.ToString(), out rez) || Convert.ToDouble(e.FormattedValue) <0)
{
//выдаем сообщение об ошибке
MessageBox.Show("Оклад должен быть числом и не может быть отрицательным. \nНе знаете размер оклада, введите 0",
"Ошибка ввода",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
//отменяем операцию ввода
e.Cancel = true;
}
}
Создание страничных форм
Страничная форма позволяет просматривать данные из таблицы по одной записи. Такая форма может содержать компоненты, которые максимально облегчают пользовательский ввода данных. Например, помимо текстовых полей можно использовать флажки, выпадающие списки, графические компоненты для просмотра графических изображений, календари и т.п.
Для создания такой формы подключите нужную таблицу с помощью сетки DataGridView, затем сетку удалите. на форме останется два компонента BindingSource и TableAdapter.
Для каждого поля таблицы нанесите на форму соответствующие компоненты. Каждый компонент привязывается к полю таблицы с помощью свойства DataBinding, внутри которого для свойства, отвечающего за содержимое компонента, выберите BindingSource соответствующей таблицы, а в нем имя нужного поля таблицы БД.
Например, пусть таблица sotr имеет поле foto. Нанесем на форму компонент PictureBox, откроем его свойство DataBindings, найдем в списке свойство Image (оно отвечает за содержимое поля PictureBox) и свяжем его с полем таблицы как показано на рисунке.

Аналогично можно привязать другие компоненты через соответствующие свойства:
- TextBox через свойство Text;
- ComboBox и ListBox через свойство Text (если набор значений списка фиксированный) или SelectedValue (если набор значений списка берется из набора данных);
- DateTimePicker через свойство Value;
- RadioButton и CheckBox через свойство Checked и т.д.
Работа с графическими полями
Если в таблице предусмотрено хранение изображений, то для отображения таких данных используют компонент PictureBox, а для заполнения данного компонента используют компонент OpenFileDialog.
Пример: Пусть в компоненте PictureBox отображается содержимое поле foto. Данный компонент заполняется двойным щелчком на нем. В событии DoubleClick компонента PictureBox напишем код:
private void pictureBox1_DoubleClick(object sender, EventArgs e)
{
if (openFileDialog1.ShowDialog() == DialogResult.OK)
pictureBox1.Image = Image.FromFile(openFileDialog1.FileName);
}
Замечание. Не забудьте задать для диалога открытия файла список допустимых типов шрафических файлов в свойстве Filter (см. лекцию № 8) . Для компонента PictureBox задайте масштабирование изображений: SizeMode = Zoom.
Работа с полями дата/время
Заполнять дату с клавиатуры в обычном текстовом поле нежелательно, так как, в случае ошибки ввода, данные не сохранятся и программа завершит работу. Для ввода дат рекомендуется использовать компонент DateTimePicker, который представляет собой выпадающий список с календарем. Для работы с ним нанесите компонент на форму, откройте его свойство DataBindings, найдите свойство Value и укажите в нем поле Дата/Время из таблицы БД.
Если на форме есть достаточно места, то вместо выпадающего календаря можно использовать компонент MonthCalendar, который связывается с полем таблицы через свойство DataBindings - SelectionRange.
Использование списков при заполнении полей
Если значение поля таблицы может быть заполнено значением из некоторого фиксированного набора (пол, месяцы года, дни недели, разряды и т.п.), то для таких полей целесообразно использовать компонент ComboBox, в свойстве Items которого можно ввести перечень допустимых значений, в свойстве DataBindings свяжите свойство SelectedValue с полем таблицы. Использование такого компонента с одной стороны освобождает пользователя от ввода данных с клавиатуры, а с другой защищает программу от ошибок ввода, опечаток и т.п.
Однако часто текстовые поля заполняются значениями из динамических наборов данных. Такие наборы могут пополняться новыми значениями, или из них могут удаляться существующие значения. В этом случае такой перечень значений может храниться в отдельной таблице-справочнике.
В базе данных создайте таблицу-справочник для хранения некоторого перечня допустимых значений поля. Данная таблица должна быть связана с исходной таблицей по ключевому полю.
Для создания списков на основании таблицы-справочника подключите эту таблицу с помощью сетки, а затем сетку удалите. В результате на форме останется два компонента BindingSource и TableAdapter для таблицы.
Для компонента ComboBox задайте свойства:
- через DataBindings свяжите свойство SelectedValue с полем таблицы;
- DataSource - укажите BindingSource для таблицы справочника;
- DataMember - укажите поле таблицы-справочника, значения которого будут отображаться в перечне выпадающего списка;
- ValueMember - укажите поле таблицы-справочника, по которому она связана с основной таблицей.
Навигация по записям
Для выполнения переходов по записям в таблице и выполнения операций по редактированию данных имеется компонент BindingNavigator, который представляет собой панель с набором кнопок для выполнения ряда действий с данными.

Для связывания этого компонента с нужной таблицей в его свойстве BindingSource укажите имя компонента BindingSource, связанного с таблицей.
Кнопка добавления (плюс) добавляет новую запись в конец сетки.
Кнопка удаления (крест) удаляет запись в сетке, НО НЕ В ТАБЛИЦЕ! Чтобы удаление происходило в таблице, необходимо вызывать специальный метод сохранения изменений в БД, который будет рассмотрен ниже. Кроме этого, перед удалением не выводится диалог на подтверждение операции, что неправильно с точки зрения защиты данных от ошибок пользователя.
Если нужно переопределить код для указанных кнопок, то выделите компонент BindingNavigator и очистите свойства AddNewItem (для кнопки Добавить) и DeleteItem (для кнопки удалить). Затем для этих кнопок введите свой код в событии Click.
Перечень всех элементов, отображаемых на компоненте BindingNavigator, можно увидеть в свойстве Items компоненте BindingNavigator. Можно добавить, удалить или изменить порядок компонентов на форме. При этом каждая кнопка на панели навигации имеет собственные свойства.
Ограничение ввода в полях на страничной форме
Если при вводе данных в поле таблицы нужно применить ограничение, то в событии Validating тестового поля нужно писать код, проверяющий введенное значение.
Например, пусть в таблице есть поле oklad, которое связано с текстовым полем на форме. Нужно запретить вводить не числовые значения, а также значения меньше 0. При этом, если пользователь не знает значение оклада, то может ввести 0, чтобы пропустить это поле.
private void textBox1_Validating(object sender, CancelEventArgs e)
{
//если в поле введено значение 0,
//то проверка не выполняется
if (textBox1.Text == "0") return;
//переменная для конвертирования из текста в число
double rez;
//если в поле введено не число
//или введено число, но отрицательное
if (!double.TryParse(textBox1.Text, out rez) || Convert.ToDouble(textBox1.Text) < 0)
{
//выдаем сообщение об ошибке ввода
MessageBox.Show("Оклад не может быть меньше 1000. \nНе знаете размер оклада, введите 0",
"Ошибка ввода",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
//отменяем ввод
e.Cancel = true;
}
}
Комбинирование табличных и страничных форм
Табличные формы имеют недостатки, связанные с тем, что в сетке невозможно отобразить флажки, графические поля, списки для облегчения ввода данных. Поэтому в реальных программах часто комбинируют табличные и страничные формы для создания удобного интерфейса.
Для этого в сетке отражают только основной набор полей, а рядом с сеткой размещают визуальные компоненты для просмотра и редактирования других полей. И сетка и визуальные компоненты ссылаются на один и тот же компонент BindingSource, связанный с нужной таблицей БД. Это позволяет при быстром и удобном перемещении по записям в сетке просматривать и редактировать поля текущей записи с помощью подходящих визуальных компонентов.
Другим вариантом может быть тот, при котором на одной форме в сетке отображается набор из основных полей, а просмотр и редактирование всей записи выполняется на вспомогательной страничном форме, которая вызывается при некоторой событии (например, добавление новой записи происходит при щелчке на кнопке, а редактирование записи происходит после двойного щелчка на нужной записи в сетке).
Такой подход требует программной настройки приложения:
- присваиваем главной форме имя
На главной форме размещаются компоненты BindingSource и TableAdapter для нужных таблиц. При создании второй страничной формы все компоненты на ней нужно будет также привязать к исходному BindingSource. По-умолчанию, это сделать невозможно, так как главная форма не имеет имени. Для присваивания главной форме имени необходимо:
1. Откройте файл Program.cs и внутри класса Program опишите переменную для главной формы:
public static Form1 form1;
2. Вместо команды Application.Run(new Form1()); введите код:
form1=new Form1();
Application.Run(form1);
В результате главная форма будет иметь имя Program.form1
- привязываем на второй страничной форме все компоненты к полям таблицы БД
1. Компоненты DataSet, BindingSource, TableAdapter делают "видимыми" для остальных форм. Для этого установите свойство Modifiers=Public
2. На второй форме разместите компоненты для полей таблицы и в событии Load формы введите команды привязки компонентов с полями таблицы.
Примеры. Поле fam привязываем к тестовому полю.
textBox1.DataBindings.Add(new Binding("Text", Program.form1.sotrBindingSource, "fam", true));
Поле datar (дата рождения) привязываем к календарю DateTimePicker.
dateTimePicker1.DataBindings.Add(new Binding("Value",Program.form1.sotrBindingSource, "datar", true));
Поле foto привязываем к компоненту Picture Box.
pictureBox1.DataBindings.Add(new Binding("Image", Program.form1.sotrBindingSource, "foto", true));
Поле dolg (должность) привязываем к компоненту ComboBox.
comboBox1.DataBindings.Add(new Binding("SelectedValue", Program.form1.sotrBindingSource, "dolg", true));
Пусть должность сотрудника заполняется с помощью таблицы-справочника dolg. Таблица-справочник dolg связана с исходной таблицей sotr по полю id_dolg. Необходимо на страничной форме создать выпадающий список для заполнения должности сотрудника.
Сначала подключите на форму таблицу dolg. Для компонентов BindingSource и TableAdapter таблицы dolg зададим свойство Modifiers=Public.
В событии Load страничной формы введите код привязки выпадающего списка.
//выпадающий список заполняется значениями из таблицы dolg
comboBox1.DataSource = Program.form1.dolgBindingSource;
//пользователь видит в списке названия должностей (поле dolg)
comboBox1.DisplayMember = "dolg";
//таблица-справочник связана с основной таблицей по полю id_dolg
comboBox1.ValueMember = "id_dolg";
//выпадающий список привязан к полю основной таблицы
comboBox1.DataBindings.Add(new Binding("SelectedValue", Program.form1.sotrBindingSource, "id_dolg", true));
4. Методы и свойства для работы с данными в таблице
Компонент BindingSource имеет ряд методов, позволяющих выполнить навигацию или изменение данных в таблице.
Методы навигации
Методы навигации позволяют выполнять переходы по записям. К таким методам относятся:
BindingSource.MoveFirst(); // переход на первую запись
BindingSource.MovePrevious(); // переход на предыдущую запись
BindingSource.MoveNext(); // переход на следующую запись
BindingSource.MoveLast(); // переход на последнюю запись
ADOTable1.MoveBy(n) // переход на запись с номером n
Также при навигации используются некоторые свойства компонента BindingSource:
BindingSource.Position - номер текущей записи (нумерация с 0)
BindingSource.Count - общее число записей
Если необходимо проверить достижение начала или конца набора данных, то можно использовать операторы вида:
//достигнуто начало набора данных
if (BindingSource.Position==0)
//достигнут конец набора данных
if (BindingSource.Position==BindingSource.Count-1)
Методы редактирования
Методы редактирования позволяют изменять данные в таблице. К таким методам относятся:
BindingSource.AddNew(); // добавить запись в конец таблицы
BindingSource.RemoveCurrent() // удалить запись
BindingSource.CancelEdit(); //отменяет ввод в таблицу
BindingSource.EndEdit(); // завершает ввод записи
BindingSource.ResetCurrentItem(); //перегрузить текущую запись
BindingSource.ResetBindings(); //перезагрузить набор данных
Сохранение изменений в таблице
Любой метод BindingSource работает с данными, расположенными в компоненте TableAdapter. В этом компоненте находится копия таблицы и все изменения не попадают в БД. Поэтому любая операция изменения данных должна заканчиваться командой обновления данных в БД. Команда имеет вид:
TableAdapter.Update(DataSet.имя_таблицы);
Пример, напишем код удаления данных из таблицы sotr.
if (MessageBox.Show("Удалить данные о сотруднике?",
"Подтвердите операцию",
MessageBoxButtons.YesNo,
MessageBoxIcon.Question) == DialogResult.Yes)
{
sotrBindingSource.RemoveCurrent();
sotrTableAdapter.Update(sotrDataSet.sotr);
}
Пример, напишем код сохранения данных в таблицу БД.
Validate();
sotrBindingSource.EndEdit();
sotrTableAdapter.Update(sotrDataSet.sotr);
Пример. Пусть в таблице нужно посчитать оклад сотрудников на 300. Поле имеет имя oklad.
//переменная для записи номера текущей записи
int pos = sotrBindingSource.Position;
//переменная для расчета суммы
double sum=0;
//переходим в начало таблицы
sotrBindingSource.MoveFirst();
//запускаем цикл по таблице
foreach (DataRowView row in sotrBindingSource)
//суммируем оклад очередной записи
sum += Convert.ToDouble(row["oklad"]);
//возвращаем указатель на сохраненную позицию
sotrBindingSource.Position=pos;
//выводим сумму в окне сообщения
MessageBox.Show("Сумма = " + sum.ToString());
Пример. Пусть имеется некоторая форма с данными. Необходимо в компоненте label1 отображать текущий номер записи и общее число записей. При переходе между записями для компонента BindingSource наступает событие CurrentChanged. В этом событии нужно написать код:
private void sotrBindingSource_CurrentChanged(object sender, EventArgs e)
{
label1.Text = (sotrBindingSource.Position + 1).ToString() + " из " + sotrBindingSource.Count.ToString();
}
Вопросы для самоконтроля
1. Как выполнить подключение БД к проекту?
2. Какие операции можно выполнить над таблицами при настройке соединения? Как создать вычисляемое поле?
3. Как создать страничную форму? Как задать пароль для БД в строке подключения?
4. Как обратиться к полю таблицы в коде? В каком событии сетки ограничивают ввод в поле?
5. Как создать страничную форму? Как создать на форме список-справочник?
6. Опишите компонент для навигации по таблице БД? Как изменить кнопки на панели навигации и переписать для них код?
7. Как создать отдельную страничную форму и привязать ее компоненты к таблице на главной форме?
8. Опишите методы навигации по таблице и методы редактирования данных?
9. Как сохранить изменения в таблице БД? Приведите пример удаления и сохранения данных в таблице БД.