Обработка исключения параллелизма в приложениях базы данных платформа .NET Framework
Примечание.
Наборы данных и связанные классы являются устаревшими технологиями платформа .NET Framework с начала 2000-х годов, которые позволяют приложениям работать с данными в памяти во время отключения приложений от базы данных. Технологии особенно полезны для приложений, которые позволяют пользователям изменять данные и сохранять изменения обратно в базу данных. Хотя наборы данных оказались очень успешными, мы рекомендуем новым приложениям .NET использовать Entity Framework Core. Entity Framework предоставляет более естественный способ работы с табличными данными в виде объектных моделей, и он имеет более простой интерфейс программирования.
Исключения параллелизма возникаютSystem.Data.DBConcurrencyException при попытке двух пользователей одновременно изменить одни и те же данные в базе данных. В этом пошаговом руководстве вы создадите приложение Windows, которое иллюстрирует, как поймать DBConcurrencyExceptionстроку, найдите строку, вызвавшей ошибку, и узнайте стратегию обработки.
В этом пошаговом руководстве описан следующий процесс.
Создайте проект приложения Windows Forms (платформа .NET Framework).
Создайте новый набор данных на основе таблицы Northwind Customers.
Создайте форму с DataGridView отображением данных.
Заполните набор данных данными из таблицы Customers в базе данных Northwind.
Используйте функцию "Показать данные таблицы" в обозревателе серверов, чтобы получить доступ к данным таблицы "Клиенты" и изменить запись.
Измените ту же запись на другое значение, обновите набор данных и попытайтесь записать изменения в базу данных, что приводит к возникновению ошибки параллелизма.
Перехватите ошибку, а затем отобразите различные версии записи, позволяя пользователю определить, следует ли продолжать и обновлять базу данных, или отменить обновление.
Необходимые компоненты
В этом пошаговом руководстве используется SQL Server Express LocalDB и пример базы данных Northwind.
Если у вас нет SQL Server Express LocalDB, установите его на странице скачивания SQL Server Express или с помощью Установщика Visual Studio. В установщике Visual Studio можно установить SQL Server Express LocalDB как часть рабочей нагрузки хранилища данных и обработки или как отдельный компонент.
Установите пример базы данных Northwind, выполнив следующие действия.
В Visual Studio откройте окно обозреватель объектов SQL Server. (SQL Server обозреватель объектов устанавливается как часть рабочей нагрузки хранилища данных и обработки в Visual Studio Installer.) Разверните узел SQL Server. Щелкните правой кнопкой мыши экземпляр LocalDB и выберите новый запрос.
Откроется окно редактора запросов.
Скопируйте скрипт Northwind Transact-SQL в буфер обмена. Этот скрипт T-SQL создает базу данных Northwind с нуля и заполняет ее данными.
Вставьте скрипт T-SQL в редактор запросов и нажмите кнопку "Выполнить ".
Через некоторое время запрос завершает работу и создается база данных Northwind.
Создание нового проекта
Начните с создания нового приложения Windows Forms:
В Visual Studio в меню Файл выберите пункты Создать>Проект.
Разверните Visual C# или Visual Basic в левой области, а затем выберите "Рабочий стол Windows".
В средней области выберите тип проекта приложения Windows Forms.
Назовите проект ConcurrencyWalkthrough и нажмите кнопку "ОК".
Проект ConcurrencyWalkthrough создается и добавляется в Обозреватель решений, а новая форма открывается в конструкторе.
Создание набора данных Northwind
Затем создайте набор данных с именем NorthwindDataSet:
В меню "Данные" выберите "Добавить новый источник данных".
Открывается мастер настройки источника данных.
На экране "Выбор типа источника данных" выберите "База данных".
Выберите подключение к образцу базы данных Northwind из списка доступных подключений. Если подключение недоступно в списке подключений, выберите "Создать подключение".
Примечание.
Если вы подключаетесь к локальному файлу базы данных, выберите "Нет ", если вы хотите добавить этот файл в проект.
На экране "Сохранить строка подключения" на экране файла конфигурации приложения нажмите кнопку "Далее".
Разверните узел "Таблицы" и выберите таблицу "Клиенты". Имя набора данных по умолчанию должно быть NorthwindDataSet.
Нажмите кнопку "Готово ", чтобы добавить набор данных в проект.
Создание элемента управления DataGridView с привязкой к данным
В этом разделе описаноSystem.Windows.Forms.DataGridView, как перетащить элемент "Клиенты" из окна "Источники данных" в форму Windows Form.
Чтобы открыть окно "Источники данных" , в меню "Данные " выберите " Показать источники данных".
В окне "Источники данных" разверните узел NorthwindDataSet и выберите таблицу "Клиенты".
Щелкните стрелку вниз на узле таблицы и выберите DataGridView в раскрывающемся списке.
Перетащите таблицу в пустую область формы.
Элемент DataGridView управления с именем CustomersDataGridView и именованный BindingNavigator CustomersBindingNavigator добавляются в форму, привязанную к объекту BindingSource. Это, в свою очередь, привязано к таблице Customers в NorthwindDataSet.
Проверка формы
Теперь вы можете протестировать форму, чтобы убедиться, что она ведет себя должным образом до этой точки:
Выберите F5 , чтобы запустить приложение.
Форма отображается с элементом DataGridView управления, заполненным данными из таблицы Customers.
В меню Отладка выберите команду Остановить отладку.
Обработка ошибок параллелизма
Обработка ошибок зависит от конкретных бизнес-правил, управляющих приложением. В этом пошаговом руководстве мы используем следующую стратегию в качестве примера для обработки ошибки параллелизма.
Приложение предоставляет пользователю три версии записи:
Текущая запись в базе данных
Исходная запись, загруженная в набор данных
Предлагаемые изменения в наборе данных
Затем пользователь может перезаписать базу данных с предлагаемой версией или отменить обновление и обновить набор данных новыми значениями из базы данных.
Включение обработки ошибок параллелизма
Создайте пользовательский обработчик ошибок.
Отображение вариантов для пользователя.
Обработайте ответ пользователя.
Повторно отправьте обновление или сбросьте данные в наборе данных.
Добавление кода для обработки исключения параллелизма
При попытке выполнить обновление и возникает исключение, обычно требуется сделать что-то с информацией, предоставленной вызванным исключением. В этом разделе вы добавите код, который пытается обновить базу данных. Вы также обрабатываете любые DBConcurrencyException возникающие исключения, а также любые другие исключения.
Примечание.
Далее CreateMessage
в пошаговом руководстве добавляются методы и ProcessDialogResults
методы.
Добавьте следующий код под методом
Form1_Load
:private void UpdateDatabase() { try { this.customersTableAdapter.Update(this.northwindDataSet.Customers); MessageBox.Show("Update successful"); } catch (DBConcurrencyException dbcx) { DialogResult response = MessageBox.Show(CreateMessage((NorthwindDataSet.CustomersRow) (dbcx.Row)), "Concurrency Exception", MessageBoxButtons.YesNo); ProcessDialogResult(response); } catch (Exception ex) { MessageBox.Show("An error was thrown while attempting to update the database."); } }
Замените
CustomersBindingNavigatorSaveItem_Click
метод для вызоваUpdateDatabase
метода, чтобы он выглядел следующим образом:
Отображение вариантов для пользователя
Код, который вы только что написали, вызывает процедуру CreateMessage
для отображения сведений об ошибке пользователю. В этом пошаговом руководстве вы используете поле сообщения для отображения различных версий записи пользователю. Это позволяет пользователю выбрать, следует ли перезаписать запись изменениями или отменить изменение. Когда пользователь выбирает параметр (нажимает кнопку) в поле сообщения, ответ передается методу ProcessDialogResult
.
Создайте сообщение, добавив следующий код в редактор кода. Введите этот код под методом UpdateDatabase
:
private string CreateMessage(NorthwindDataSet.CustomersRow cr)
{
return
"Database: " + GetRowData(GetCurrentRowInDB(cr), DataRowVersion.Default) + "\n" +
"Original: " + GetRowData(cr, DataRowVersion.Original) + "\n" +
"Proposed: " + GetRowData(cr, DataRowVersion.Current) + "\n" +
"Do you still want to update the database with the proposed value?";
}
//--------------------------------------------------------------------------
// This method loads a temporary table with current records from the database
// and returns the current values from the row that caused the exception.
//--------------------------------------------------------------------------
private NorthwindDataSet.CustomersDataTable tempCustomersDataTable =
new NorthwindDataSet.CustomersDataTable();
private NorthwindDataSet.CustomersRow GetCurrentRowInDB(NorthwindDataSet.CustomersRow RowWithError)
{
this.customersTableAdapter.Fill(tempCustomersDataTable);
NorthwindDataSet.CustomersRow currentRowInDb =
tempCustomersDataTable.FindByCustomerID(RowWithError.CustomerID);
return currentRowInDb;
}
//--------------------------------------------------------------------------
// This method takes a CustomersRow and RowVersion
// and returns a string of column values to display to the user.
//--------------------------------------------------------------------------
private string GetRowData(NorthwindDataSet.CustomersRow custRow, DataRowVersion RowVersion)
{
string rowData = "";
for (int i = 0; i < custRow.ItemArray.Length ; i++ )
{
rowData = rowData + custRow[i, RowVersion].ToString() + " ";
}
return rowData;
}
Обработка ответа пользователя
Вам также нужен код для обработки ответа пользователя на поле сообщения. Эти параметры можно либо перезаписать текущую запись в базе данных с предлагаемым изменением, либо отказаться от локальных изменений и обновить таблицу данных с записью, которая сейчас находится в базе данных. Если пользователь выбирает "Да", Merge метод вызывается с аргументом preserveChanges, равным true. Это приводит к успешному выполнению попытки обновления, так как исходная версия записи теперь соответствует записи в базе данных.
Добавьте следующий код ниже кода, добавленного в предыдущем разделе:
// This method takes the DialogResult selected by the user and updates the database
// with the new values or cancels the update and resets the Customers table
// (in the dataset) with the values currently in the database.
private void ProcessDialogResult(DialogResult response)
{
switch (response)
{
case DialogResult.Yes:
northwindDataSet.Merge(tempCustomersDataTable, true, MissingSchemaAction.Ignore);
UpdateDatabase();
break;
case DialogResult.No:
northwindDataSet.Merge(tempCustomersDataTable);
MessageBox.Show("Update cancelled");
break;
}
}
Тестирование поведения формы
Теперь можно протестировать форму, чтобы убедиться, что она работает должным образом. Чтобы имитировать нарушение параллелизма, измените данные в базе данных после заполнения NorthwindDataSet.
Выберите F5 , чтобы запустить приложение.
После появления формы оставьте его запущенным и переключитесь в интегрированную среду разработки Visual Studio.
В меню Вид выберите Обозреватель серверов.
В обозревателе серверов разверните подключение, которое использует приложение, а затем разверните узел таблиц .
Щелкните правой кнопкой мыши таблицу "Клиенты" , а затем выберите "Показать данные таблицы".
В первой записи (ALFKI) измените ContactName на Maria Anders2.
Примечание.
Перейдите к другой строке, чтобы зафиксировать изменение.
Переключитесь на запущенную форму ConcurrencyWalkthrough.
В первой записи формы (ALFKI) измените ContactName на Maria Anders1.
Выберите кнопку Сохранить.
Возникает ошибка параллелизма, и появится поле сообщения.
При нажатии кнопки "Нет отмены" обновления и обновления набора данных со значениями, которые в настоящее время находятся в базе данных. При выборе "Да" в базу данных записывается предлагаемое значение.