Рекомендации ADO.NET для области подключения и объекта DataAdaptor
Это мой первый пост на StackOverflow, так что будьте осторожны ...
У меня есть несколько вопросов относительно области объекта для ADO.NET.
Когда я подключаюсь к базе данных, я обычно использую такой код:
OleDbConnection conn = new OleDbConnection("my_connection_string");
conn.Open();
OleDbDataAdapter adapter = new OleDbDataAdapter("SELECT * from Employees", conn);
OleDbCommandBuilder cb = new OleDbCommandBuilder(adapter);
DataTable dt = new DataTable();
adapter.Fill(dt);
conn.Close();
conn.Dispose();
Допустим, я привязываю полученный DataTable к элементу управления сеткой и разрешаю пользователям редактировать содержимое сетки. Теперь, когда мои пользователи нажимают кнопку «Сохранить», мне нужно вызвать этот код:
adapter.Update(dt);
Вот мои вопросы:
1) Нужно ли мне сохранять объект адаптера, который я создал при первоначальной загрузке таблицы данных, или я могу создать другой объект адаптера в событии нажатия кнопки «Сохранить» для выполнения обновления?
2) Если мне нужно сохранить исходный объект адаптера, нужно ли мне также оставить доступным и открытым объект подключения?
Я понимаю отключенную модель ADO.NET - я просто запутался в области объекта, когда пришло время обновить базу данных. Если бы кто-нибудь мог дать мне несколько советов о лучших практиках для этого сценария, я был бы очень признателен!
Заранее спасибо...
Ответов (3)3
1) Вам не нужен тот же DataAdapter, но если вы создаете новый, он должен использовать тот же запрос, что и его основа.
2) DataAdapter откроет свое соединение, если соединение будет закрыто. В этом случае он снова закроет соединение после того, как это будет сделано. Если соединение уже открыто, оно останется открытым даже после его завершения.
Обычно вы будете работать так, как в вашем примере. Создайте Conneciton и DataAdapter, заполните DataTable и затем удалите Connection и DataAdapter.
Два комментария к вашему коду:
- Здесь вам не нужен CommandBuilder, поскольку вы делаете только выбор. Построитель команд необходим только в том случае, если вы хотите автоматически генерировать операторы Insert, Update или Delete. В этом случае вам также необходимо вручную установить InsertCommand, UpdateCommand или DeleteCommand в DataAdapter из CommandBuilder.
- Второй. Вместо того, чтобы вызывать Dispose вручную, вы должны использовать предложение Using. Это гарантирует, что ваши объекты будут удалены, даже если возникнет исключение.
Попробуйте изменить свой код на этот:
DataTable dt = new DataTable();
using (OleDbConnection conn = new OleDbConnection("my_connection_string"))
using (OleDbDataAdapter adapter = new OleDbDataAdapter("SELECT * from Employees", conn))
{
adapter.Fill(dt);
}
Обратите внимание, что я определяю DataTable вне предложений using. Это необходимо для того, чтобы таблица была в области видимости, когда вы оставите использование. Также обратите внимание, что вам не нужен вызов Dispose для DataAdapter или вызов Close для Connection. И то, и другое делается неявно, когда вы покидаете использование.
Ой. И добро пожаловать в SO :-)
Есть две дополнительные детали, которые стоит добавить к отличному ответу Руне Гримстад.
Во-первых, CommandBuilder (если он необходим) реализует IDisposable, поэтому его следует заключить в собственный оператор using. Удивительно (по крайней мере, для меня), Disposing the DataAdapter не похоже на Dispose связанный CommandBuilder. Проблема, которую я заметил, когда мне не удалось это сделать, заключалась в том, что, хотя я вызвал Dispose в DataAdapter и состояние подключения было «Closed», я не смог удалить временную базу данных после того, как использовал CommandBuilder для обновления этой базы данных.
Во-вторых, утверждение ... В этом случае вам также необходимо вручную установить InsertCommand, UpdateCommand или DeleteCommand в DataAdapter ... » не всегда правильно. Во многих тривиальных случаях CommandBuilder автоматически создает правильные операторы INSERT, UPDATE и DELETE на основе оператора SELECT, предоставленного DataAdapter, и метаданных из базы данных. «Тривиальный» в данном случае означает, что осуществляется доступ только к одной таблице, и эта таблица имеет первичный ключ, который возвращается как часть оператора SELECT.
Чтобы ответить на ваши вопросы:
В идеале вы должны сохранить тот же DataAdapter, потому что он уже выполнил свою инициализацию. DataAdapter предоставляет такие свойства, как SelectCommand, UpdateCommand, InsertCommand и DeleteCommand, которые позволяют вам устанавливать различные объекты Command для выполнения этих различных функций в источнике данных. Итак, как видите, DataAdapter предназначен для повторного использования для нескольких команд (для одного и того же соединения с базой данных). Использование CommandBuilder (хотя и не рекомендуется) создает другие команды путем анализа SelectCommand, что позволяет вам выполнять обновления, удаления и вставки с использованием того же CommandBuilder.
Лучше всего позволить DataAdapter неявно обрабатывать соединения с базой данных. @Rune Grimstad уже подробно рассказывал об этом неявном поведении, и это полезно понять. В идеале соединения должны быть закрыты как можно скорее.