Опубликован: 11.09.2006 | Уровень: специалист | Доступ: свободно
Лекция 4:

Работа с данными

Изменение записей

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

Создайте новый проект и назовите его Change_Data. На этот раз мы поработаем с компонентами ADO.NET, и привязывать данные к элементам управления будем, также устанавливая соответствующие свойства в режиме дизайна. Для ускорения разработки интерфейса выделяем все надписи и текстовые поля в режиме дизайна формы в проекте DataBindings, и копируем их. Располагаем вставленные элементы на форме проекта Change_Data — при этом мы избавляемся от необходимости определять свойства Name и Text. Перетаскиваем компонент oleDbDataAdapter и устанавливаем соединение с таблицей "Поставщики" базы данных Microsoft Access RBProduct.mdb. Генерируем объект DataSet и называем его dsProviders. Связываем текстовые поля с соответствующими столбцами таблицы "Поставщики", используя свойство DataBindings (см. рис. 4.51). Переходим в код формы. В конструкторе формы после InitializeComponent вызываем метод Fill объекта DataAdapter:

oleDbDataAdapter1.Fill(dsProviders1);

Проверяем приложение, запуская его. Далее добавляем кнопки для навигации по записям и соответствующие обработчики, используя объект CurrencyManager (можно также воспользоваться готовым проектом DataBindings, изменяя названия объекта DataSet ). Добавим теперь кнопки для добавления и удаления записей. Располагаем на форме две кнопки — "Добавить" и "Удалить", в свойстве Name устанавливаем значения btnAdd и btnRemove соответственно. В обработчике кнопки "Добавить" вызываем метод AddNew объекта CurrencyManager:

private void btnAdd_Click(object sender, System.EventArgs e)
{
  cmRecords.AddNew();
}

Для обработчика кнопки "Удалить" также используем встроенный метод RemoveAt, причем если на форме не будет записей, то вызываем окно предупреждения:

private void btnRemove_Click(object sender, System.EventArgs e)
{
 if(cmRecords.Count>0)cmRecords.RemoveAt(cmRecords.Position);
 else MessageBox.Show("Нет записи для удаления!", "Удаление записи", 
 MessageBoxButtons.OK, MessageBoxIcon.Error);

}

Запускаем приложение. Теперь можно добавлять и удалять записи — однако все сделанные изменения хранятся в объекте DataSet и не передаются в базу данных. Перезапустив приложение, мы обнаружим, что все записи остались прежними. Добавляем кнопку "Обновить", свойству Name этой кнопки устанавливаем значение btnUpdate. В обработчике кнопки создаем новый объект DataSet changes, в который будут записываться все изменения старого DataSet dsProviders1. Методу Update объекта oleDbDataAdapter1 передаем новый DataSet changes и, наконец, вызываем метод AcceptChanges для подтверждения изменений:

private void btnUpdate_Click(object sender, System.EventArgs e)
{
DataSet changes = dsProviders1.GetChanges();
  oleDbDataAdapter1.Update(changes);
  dsProviders1.AcceptChanges();
}

Запускаем приложение, вносим новую запись и нажимаем кнопку "Обновить". Возникает ошибка — Additional information: Value cannot be null — "Дополнительная информация, значение не может быть равным нулю". Дело в том, что объект CurrencyManager сохраняет изменения в DataSet после того, как мы перейдем от редактируемой записи к следующей. Но кроме этого, подобная функциональность кнопки "Обновить" нас не может устраивать. Поэтому добавим блок для обработки исключений, который будет проверять наличие изменений в dsProviders1:

private void btnUpdate_Click(object sender, System.EventArgs e)
{
  if (dsProviders1.HasChanges())
    try
    {
    DataSet changes = dsProviders1.GetChanges();
    oleDbDataAdapter1.Update(changes);
    dsProviders1.AcceptChanges();
    }

    catch(Exception ex)
    {
MessageBox.Show(ex.Message, "Неудачное обновление", MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
      else        
MessageBox.Show("Нет записей для изменения", "Изменение записей", MessageBoxButtons.OK, MessageBoxIcon.Information);
        
}
Листинг 4.24.

Теперь, если мы попытаемся внести изменения, не переходя к следующей записи, появится окно предупреждения "Нет записей для изменения". Более того, если связывание с базой данных окажется невозможным, — например, она заблокирована, — то в окне "Неудачное обновление" выйдет сообщение с кодом ошибки. Для того чтобы пользователю не приходилось задумываться о работе CurrencyManager, добавим в код кнопки "Обновить" отключение остальных кнопок на время редактирования записи:

private void btnAdd_Click(object sender, System.EventArgs e)
{
  cmRecords.AddNew();
  btnFirst.Enabled = false;
  btnLast.Enabled = false;
  btnNext.Enabled = false;
  btnPrevious.Enabled = false;
  btnRemove.Enabled = false;
  btnUpdate.Enabled = false;
    
}

Для возврата к обычному режиму добавим на форму кнопку "Сохранить", которая будет возвращать позицию на первую запись и включать остальные кнопки:

private void btnSave_Click(object sender, System.EventArgs e)

{
  cmRecords.Position = 0;
  btnFirst.Enabled = true;
  btnLast.Enabled = true;
  btnNext.Enabled = true;
  btnPrevious.Enabled = true;
  btnRemove.Enabled = true;
  btnUpdate.Enabled = true;
}

Теперь наше приложение может просматривать, изменять и сохранять записи в базе данных (рис. 4.56).

Готовое приложение проекта Change_Data

Рис. 4.56. Готовое приложение проекта Change_Data

На диске, прилагаемом к книге, вы найдете проект Change_Data (Code\Glava4 Change_Data).

Елена Дьяконова
Елена Дьяконова

При нажатии на Сумма в примере ArbitraryMethod из Лекция 7, VS 2013 выдается ошибка: 

Необработанное исключение типа "System.InvalidOperationException" в System.Windows.Forms.dll

Дополнительные сведения: Недопустимая операция в нескольких потоках: попытка доступа к элементу управления "lblResult" не из того потока, в котором он был создан.

Затем:

Необработанное исключение типа "System.InvalidOperationException" в mscorlib.dll

Дополнительные сведения: Для каждой асинхронной операции метод EndInvoke может вызываться только один раз.

Александр Сороколет
Александр Сороколет

Свойство WindowState формы blank Maximized. Не открывается почемуто на всё окно, а вот если последующую форму бланк открыть уже на макс открывается :-/