Среда Microsoft SQL Server предоставляет средства разделенного управления объектами сервера. Для доступа используются два режима аутентификации: режим аутентификации Windows (Windows Authentication) и режим смешанной аутентификации (Mixed Mode Authentication). При установке первый режим предлагается по умолчанию, поэтому, скорее всего, ваш сервер сконфигурирован с его использованием (рис. 4.1):
(рис 4.1) Режим аутентификации Windows предлагаемый по умолчанию при установкеВ этом случае аутентификация пользователя осуществляется операционной системой Windows. Затем SQL Server использует аутентификацию операционной системы для определения уровня доступа. При подключении в окне "Свойства связи с данными" мы также указывали этот режим (рис. 4.2):
(рис 4.2) Режим аутентификации Windows в окне "Свойства связи с данными"Смешанный режим позволяет проводить аутентификацию пользователя как средствами операционной системы, так и с применением учетных записей Microsoft SQL Server. Для включения этого режима запускаем SQL Server Enterprise Manager, на узле локального сервера щелкаем правой кнопкой и выбираем пункт меню "Свойства". В появившемся окне "SQL Server Properties" переходим на вкладку "Security", устанавливаем переключатель в положение "SQL Server and Windows" (рис. 4.3).
(рис 4.3) Включение режима смешанной аутентификацииПосле подтверждения изменений закрываем окно свойств. Раскрываем узел "Security" текущего сервера, выделяем объект "Logins". В нем мы видим две записи - "BULTIN\Администраторы" и "sa". Первая из них предназначена для аутентификации учетных записей операционной системы. Вторая - "sa" (
(рис 4.4) Установка пароля на учетной записи "sa" Займемся теперь подключением к заданной базе данных, например Northwind, от имени учетной записи "sa". Создайте новое Windows-приложение, назовите его "VisualSQLUser_sa". Перетаскиваем на форму элемент управления DataGrid, его свойству Dock устанавливаем значение "Fill". В окне Toolbox переходим на вкладку Data и дважды щелкаем на объекте SqlDataAdapter. В появившемся мастере создаем новое подключение. В окне "Свойства связи с данными" указываем название локального сервера (local), имя пользователя (sa) и пароль (12345), а также базу данных Northwind (рис. 4.5):
(рис 4.5) Окно "Свойство связи с данными". Приложение VisualSQLUser_saДополнительно мы установили галочку "Разрешить сохранение пароля". При этом его значение (12345) будет сохранено в виде текста в строке connectionString. Пока мы вынуждены это сделать - интерфейс нашего приложения не предусматривает возможность ввода пароля в момент подключения. Завершаем работу мастера "Data
(рис 4.6) Диалоговое окно сохранения пароля На панели компонент формы выделяем объект DataAdapter, переходим в его окно Properties и нажимаем на ссылку "Generate dataset". Оставляем название объекта DataSet, предлагаемое по умолчанию. В конструкторе формы заполняем объект DataSet, а также определяем источник данных для элемента DataGrid:
public Form1()
{
InitializeComponent();
sqlDataAdapter1.Fill(dataSet11);
dataGrid1.DataSource = dataSet11.Tables[0].DefaultView;
}
Запускаем приложение. На форму выводятся записи таблицы Customers (рис. 4.7):
(рис 4.7) Готовое приложение VisualSQLUser_saВ программном обеспечении к курсу вы найдете приложение VisualSQL User_sa (Code\Glava2\ VisualSQLUser_sa).
Сделаем точно такое же приложение без использования визуальных средств студии. Создайте новый Windows-проект, назовите его "ProgrammSQLUser_sa". Добавляем на форму элемент управления DataGrid, его свойству Dock устанавливаем значение "Fill". Подключаем пространство имен для работы с базой:
using System.Data.SqlClient;
В классе формы создаем строки connectionString и commandText:
string connectionString = "workstation id=9E0D682EA8AE448; user id=sa;data source=\"(local)\";" + "persist security info=True;initial catalog=Northwind;password=12345"; string commandText = "SELECT * FROM Customers";
В конструкторе формы создаем все объекты ADO .NET:
public Form1()
{
InitializeComponent();
SqlConnection conn = new SqlConnection();
conn.ConnectionString = connectionString;
SqlDataAdapter dataAdapter = new SqlDataAdapter(commandText, conn);
DataSet ds = new DataSet();
dataAdapter.Fill(ds);
dataGrid1.DataSource = ds.Tables[0].DefaultView;
conn.Close();
}
В программном обеспечении к курсу вы найдете приложение Programm SQLUser_sa (Code\Glava2\ProgrammSQLUser_sa).
В отличие от подключений к базе данных Microsoft Access здесь мы не встретили никаких сложностей. Вкладка "Подключение" в окне "Свойства связи с данными" действительно предоставляет все средства для подключения к базе данных Microsoft SQL Server. Для аутентификации пользователя достаточно указать его имя и пароль.
Класс Connection поддерживает несколько событий, позволяющих отслеживать статус соединения и получать уведомляющие сообщения для экземпляра этого класса. Описание событий приводится в таблице 4.1.
| Событие | Описание |
|---|---|
Disposed |
Возникает при вызове метода Dispose экземпляра класса |
InfoMessage |
Возникает при получении информационного сообщения от поставщика данных |
StateChange |
Возникает при открытии или закрытии соединения. Поддерживается информация о текущем и исходном состояниях |
При вызове метода Dispose объекта Connection происходит освобождение занимаемых ресурсов и сборка мусора. При этом неявно вызывается метод Close.
Рассмотрим применение события StateChange и обработчик события Disposed. Создайте новое Windows-приложение и назовите его "ConnectionEventsSQL". Свойству Size формы устанавливаем значение "600;300". Помещаем на форму элемент управления DataGrid, его свойству Dock устанавливаем значение "Fill". Добавляем элемент Panel, его свойству Dock устанавливаем значение "Bottom". На панели размещаем две надписи и одну кнопку, устанавливая следующие их свойства:
| label1, свойство | Значение |
|---|---|
| Location | 8; 8 |
| Size | 208; 80 |
| Text |
| labe2, свойство | Значение |
|---|---|
| Location | 232; 8 |
| Size | 208; 80 |
| Text |
| button1, свойство | Значение |
|---|---|
| Name | btnFill |
| Location | 488; 40 |
| Text | Заполнить |
Подключаем пространство имен для работы с базой:
using System.Data.SqlClient;
В классе формы создаем строки connectionString и commandText:
string connectionString = "workstation id=9E0D682EA8AE448; packet size=4096;integrated security=SSPI;data source=\"(local)\"; persist security info=False;initial catalog=Northwind"; string commandText = "SELECT * FROM Customers";
Объекты ADO .NET будем создавать в обработчике события Click кнопки "btnFill":
private void btnFill_Click(object sender, System.EventArgs e)
{
SqlConnection conn = new SqlConnection();
conn.ConnectionString = connectionString;
//Делегат EventHandler связывает метод-обработчик conn_Disposed
//с событием Disposed объекта conn
conn.Disposed+=new EventHandler(conn_Disposed);
//Делегат StateChangeEventHandler связывает метод-обработчик
//conn_StateChange с событием StateChange объекта conn
conn.StateChange+= new StateChangeEventHandler(conn_StateChange);
SqlDataAdapter dataAdapter = new SqlDataAdapter(commandText, conn);
DataSet ds = new DataSet();
dataAdapter.Fill(ds);
dataGrid1.DataSource = ds.Tables[0].DefaultView;
//Метод Dispose, включающий в себя метод Close,
//разрывает соединение и освобождает ресурсы.
conn.Dispose();
}
Не забывайте про возможности IntelliSense - как всегда, для создания методов-обработчиков дважды нажимаем клавишу TAB (рис. 4.8):
(рис 4.8) Автоматическое создание методов-обработчиковВ методе conn_Disposed просто выводим текстовое сообщение в надпись "label2":
private void conn_Disposed(object sender, EventArgs e)
{
label2.Text+="Событие Dispose";
}
При необходимости в этом методе могут быть определены соответствующие события. В методе conn_StateChange будем получать информацию о текущем и исходном состояниях:
private void conn_StateChange(object sender, StateChangeEventArgs e)
{
label1.Text+="\nИсходное состояние: "+e.OriginalState.ToString()
+ "\nТекущее состояние: "+ e.CurrentState.ToString();
}
Запускаем приложение. До открытия соединения состояние объекта conn было закрытым. В момент открытия текущим состоянием становится открытое, а предыдущим - закрытое. Этому соответствуют первые две строки, выведенные в надпись (рис. 4.9):
(рис 4.9) Готовое приложение ConnectionEventsSQLПосле закрытия соединения (вызова метода Dispose ) текущим состоянием становится закрытое, а предыдущим - открытое. Этому соответствуют последние две строки, выводимые в надпись.
Конечно, в таком предельно простом приложении и так ясен статус соединения. Но сама идея может применяться в любых, сколь угодно сложных приложениях, когда необходимо определять статус одного из нескольких подключений.
В программном обеспечении к курсу вы найдете приложение Connection EventsSQL (Code\Glava2\ ConnectionEventsSQL).
Создадим теперь аналогичное приложение, использующее базу данных Microsoft Access. Для того чтобы не терять время на создание пользовательского интерфейса, скопируйте папку приложения Connection EventsSQL и назовите ее "ConnectionEventsMDB". Перейдем к редактированию кода. Подключаем пространство имен для работы с базой данных:
using System.Data.OleDb;
В классе формы создаем строки connectionString и commandText:
string connectionString = @"Provider=""Microsoft.Jet.OLEDB.4.0" "; Data Source=""E:\Program Files\Microsoft Visual Studio .NET 2003\Crystal Reports\Samples\Database\xtreme.mdb"";User ID=Admin;Jet OLEDB:Encrypt Database=False"; string commandText = "SELECT * FROM Customer";
Здесь мы снова будем подключаться к базе данных xtreme.mdb. Обработчик события Click кнопки "btnFill" примет следующий вид:
private void btnFill_Click(object sender, System.EventArgs e)
{
OleDbConnection conn = new OleDbConnection();
conn.ConnectionString = connectionString;
//Делегат EventHandler связывает метод-обработчик conn_Disposed
//с событием Disposed объекта conn
conn.Disposed+=new EventHandler(conn_Disposed);
//Делегат StateChangeEventHandler связывает метод-обработчик
//conn_StateChange с событием StateChange объекта conn
conn.StateChange+= new StateChangeEventHandler(conn_StateChange);
OleDbDataAdapter dataAdapter = new OleDbDataAdapter(commandText, conn);
DataSet ds = new DataSet();
dataAdapter.Fill(ds);
dataGrid1.DataSource = ds.Tables[0].DefaultView;
//Метод Dispose, включающий в себя метод Close,
//разрывает соединение и освобождает ресурсы.
conn.Dispose();
}
Обработчики conn_Disposed и conn_StateChange будут иметь в точности такой же вид. Запускаем приложение - на форму снова выводится статус соединения (рис. 4.10):
(рис 4.10) Готовое приложение ConnectionEventsMDBВ программном обеспечении к курсу вы найдете приложение Connection EventsMDB (Code\Glava2\ ConnectionEventsMDB).
Подключение к базе данных представляет собой одно из слабых мест в работе программы. В силу самых разных причин клиент может не получить доступ к базе данных. Поэтому при создании приложения следует обязательно включать обработку исключений и возможность предоставления пользователю информации о них.
Для получения специализированных сообщений при возникновении ошибок подключения к базе данных Microsoft SQL Server используются классы SqlException и SqlErro r. Объекты этих классов можно применять для перехвата номеров ошибок, возвращаемых базой данных (таблица 4.2):
| Номер ошибки | Описание |
|---|---|
| 17 | Неверное имя сервера |
| 4060 | Неверное название базы данных |
| 18456 | Неверное имя пользователя или пароль |
Дополнительно вводятся уровни ошибок SQL Server, позволяющие охарактеризовать причину проблемы и ее сложность (таблица 4.3):
| Интервал возвращаемых значений | Описание | Действие |
|---|---|---|
| 11-16 | Ошибка, созданная пользователем | Пользователь должен повторно ввести верные данные |
| 17-19 | Ошибки программного обеспечения или оборудования | Пользователь может продолжать работу, но некоторые запросы будут недоступны. Соединение остается открытым |
| 20-25 | Ошибки программного обеспечения или оборудования | Сервер закрывает соединение. Пользователь должен открыть его снова |
Создайте новое Windows-приложение и назовите его "ExceptionsSQL". Свойству Size формы устанавливаем значение "600;380". Добавляем на форму элемент управления DataGrid, его свойству Dock устанавливаем значение "Fill". Перетаскиваем элемент Panel, определяем следующие его свойства:
| panel1, свойство | Значение |
|---|---|
| Dock | Right |
| Location | 392; 0 |
| Size | 200; 346 |
На панели размещаем четыре текстовых поля, надпись и кнопку:
| textBox1, свойство | Значение |
|---|---|
| Name | txtDataSource |
| Location | 8; 8 |
| Size | 184; 20 |
| Text | Введите название сервера |
| textBox2, свойство | Значение |
|---|---|
| Name | txtInitialCatalog |
| Location | 8; 40 |
| Size | 184; 20 |
| Text | Введите название базы данных |
| textBox3, свойство | Значение |
|---|---|
| Name | txtUserID |
| Location | 8; 72 |
| Size | 184; 20 |
| Text | Введите имя пользователя |
| textBox4, свойство | Значение |
|---|---|
| Name | txtPassword |
| Location | 8; 104 |
| Size | 184; 20 |
| Text | Введите |
| label1, свойство | Значение |
|---|---|
| Location | 16; 136 |
| Size | 176; 160 |
| Text |
| button1, свойство | Значение |
|---|---|
| Name | btnConnect |
| Location | 56; 312 |
| Size | 96; 23 |
| Text | Соединение |
Интерфейс приложения готов. Подключаем пространство имен для работы с базой данных:
using System.Data.SqlClient;
Объекты ADO .NET и весь блок обработки исключений помещаем в обработчик кнопки "Соединение":
private void btnConnect_Click(object sender, System.EventArgs e)
{
SqlConnection conn = new SqlConnection();
label1.Text = "";
try
{
//conn.ConnectionString = "workstation id=9E0D682EA8AE448;data source=\"(local)
//\";" + "persist security info=True;initial catalog=Northwind;
//user id=sa;password=12345";
//Строка ConnectionString в качестве параметров
//будет передавать значения, введенные в текстовые поля:
conn.ConnectionString =
"initial catalog=" + txtInitialCatalog.Text + ";" +
"user id=" + txtUserID.Text + ";" +
"password=" + txtPassword.Text + ";" +
"data source=" + txtDataSource.Text + ";" +
"workstation id=9E0D682EA8AE448;persist security info=True;";
SqlDataAdapter dataAdapter = new SqlDataAdapter("SELECT * FROM
Customers", conn);
DataSet ds = new DataSet();
conn.Open();
dataAdapter.Fill(ds);
dataGrid1.DataSource = ds.Tables[0].DefaultView;
}
catch (SqlException OshibkiSQL)
{
foreach (SqlError oshibka in OshibkiSQL.Errors)
{
//Свойство Number объекта oshibka возвращает
//номер ошибки SQL Server
switch (oshibka.Number)
{
case 17:
label1.Text += "\nНеверное имя сервера!";
break;
case 4060:
label1.Text += "\nНеверное имя базы данных!";
break;
case 18456:
label1.Text += "\nНеверное имя пользователя или пароль!";
break;
}
//Свойство Class объекта oshibka возвращает
//уровень ошибки SQL Server,
//а свойство Message - уведомляющее сообщение
label1.Text +="\n"+oshibka.Message + "
Уровень ошибки SQL Server: " + oshibka.Class; }
}
//Отлавливаем прочие возможные ошибки:
catch (Exception ex)
{
label1.Text += "\nОшибка подключения: " + ex.Message;
}
finally
{
conn.Dispose();
}
}
Закомментированная строка подключения содержит обычное перечисление параметров. При отладке приложения будет легче сначала добиться наличия подключения, а затем осуществлять привязку параметров, вводимых в текстовые поля. Запускаем приложение. При вводе неверных параметров в надпись выводятся соответствующие сообщения, а при правильных параметрах элемент DataGrid отображает данные (рис. 4.11):
(рис 4.11) Готовое приложение ExceptionsSQLВ программном обеспечении к курсу вы найдете приложение Exceptions SQL (Code\Glava2\ ExceptionsSQL).
Скопируйте папку приложения ExceptionsSQL и назовите ее "ExceptionsMDB". Удаляем с панели на форме имеющиеся текстовые поля и добавляем три новых:
| textBox1, свойство | Значение |
|---|---|
| Name | txtDataBasePassword |
| Location | 8; 16 |
| Size | 184; 20 |
| Text | Введите пароль базы данных |
| textBox2, свойство | Значение |
|---|---|
| Name | txtUserID |
| Location | 8; 48 |
| Size | 184; 20 |
| Text | Введите имя пользователя |
| textBox3, свойство | Значение |
|---|---|
| Name | TxtPassword |
| Location | 8; 80 |
| Size | 184; 20 |
| Text | Введите пароль пользователя |
Изменяем пространство имен для работы с базой данных:
using System.Data.OleDb;
Обработчик кнопки "Соединение" будет выглядеть так:
private void btnConnect_Click(object sender, System.EventArgs e)
{
OleDbConnection conn = new OleDbConnection();
label1.Text = "";
try
{
// conn.ConnectionString = @"Provider=""Microsoft.Jet.OLEDB.4.0"";
//Data Source=""D:\Uchebnik\Code\Glava2\BDwithUsersP.mdb"";
Jet OLEDB:System database=""D:\Uchebnik\Code\Glava2\BDWorkFile.mdw"";
User ID=Adonetuser;Password=12345;Jet OLEDB:Database Password=98765;";
//Строка ConnectionString в качестве параметров
//будет передавать значения, введенные в текстовые поля:
conn.ConnectionString =
"Jet OLEDB:Database Password=" + txtDataBasePassword.Text
+ ";" + "User ID=" + txtUserID.Text + ";" +
"password=" + txtPassword.Text + ";" +
@"Provider=""Microsoft.Jet.OLEDB.4.0"";Data
Source=""D:\Uchebnik\Code\Glava2\BDwithUsersP.mdb"";
Jet OLEDB:System database=""D:\Uchebnik\Code\Glava
\BDWorkFile.mdw"";";
OleDbDataAdapter dataAdapter =
new OleDbDataAdapter("SELECT * FROM Туристы", conn);
DataSet ds = new DataSet();
conn.Open();
dataAdapter.Fill(ds);
dataGrid1.DataSource = ds.Tables[0].DefaultView;
}
catch (OleDbException oshibka)
{
//Пробегаем по всем ошибкам
for (int i=0; i < oshibka.Errors.Count; i++)
{
label1.Text+= "Номер ошибки " + i
+ "\n" + "Сообщение: " +
oshibka.Errors[i].Message + "\n" +
"Номер ошибки NativeError: " +
oshibka.Errors[i].NativeError + "\n" +
"Источник: " + oshibka.Errors[i].Source +
"\n" + "Номер SQLState: " +
oshibka.Errors[i].SQLState + "\n";
}
}
//Отлавливаем прочие возможные ошибки:
catch (Exception ex)
{
label1.Text += "\nОшибка подключения: " +
ex.Message;
}
finally
{
conn.Dispose();
}
}
Запускаем приложение (рис. 4.12). Свойство Message возвращает причину ошибки на русском языке, поскольку установлена русская версия Microsoft Office 2003. Свойство NativeError (внутренняя ошибка) возвращает номер исключения, генерируемый самим источником данных. Вместе или по отдельности со свойством SQL State их можно использовать для создания переключателя, предоставляющего пользователю расширенную информацию (мы это делали в приложении ExceptionsSQL) .
(рис 4.12) Готовое приложение ExceptionsMDBКроме обработки исключений, здесь следует обратить внимание на интерфейс, предоставляющий возможность пользователю вводить сведения своей учетной записи. Теперь в целях безопасности приложения не нужно включать пароль в код при использовании мастеров, поскольку строка соединения будет генерироваться динамически. Разумеется, ваше приложение может иметь другой интерфейс - например, окно соединения будет появляться в дочерней форме.
В программном обеспечении к курсу вы найдете приложение Exceptions MDB (Code\Glava2\ ExceptionsMDB).
Подключение к базе данных требует затрат времени - в самом деле, необходимо установить соединение по каналам связи, пройти аутентификацию и лишь после этого можно выполнять запросы и получать данные. Клиентское приложение, взаимодействующее с базой данных и закрывающее каждый раз соединение при помощи метода Close, будет не слишком производительным: значительная часть времени и ресурсов будет тратиться на установку повторного соединения. А что, если использовать трехуровневую модель, при которой клиентское соединение будет взаимодействовать с базой данных через промежуточный сервер? В этой модели клиентское приложение открывает соединение через промежуточный сервер (рис. 4.13, А). После завершения работы соединение закрывается приложением, но промежуточный сервер продолжает удерживать его в течение заданного промежутка времени, например, 60 секунд. По истечении этого времени промежуточный сервер закрывает соединение с базой данных (рис. 4.13, Б). Если в течение этой минуты, например, после 35 секунд, клиентское приложение снова требует связи с базой данных, то сервер просто предоставляет уже готовое соединение, причем после завершения работы обнуляет счет времени и готов снова минуту ждать обращения (рис. 4.13, В).
(рис 4.13) Трехуровневая модель соединения с базой данных. А - открытие соединения, начало отсчета, Б - Закрытие соединения промежуточным сервером по истечении минуты, В - Обращение клиентского приложения и предоставление сервером соединения в течении минуты ожидания В результате использования этой модели сокращается время, необходимое для установки связи с удаленной базой данных. Можно провести аналогию со следующей ситуацией: представьте, что вам и вашим друзьям нужно поговорить с одним и тем же человеком на другом конце земного шара. Вы можете звонить по отдельности и потратить достаточно много времени на то, чтобы дозвониться до человека, дождаться, пока его позовут к телефону, и т.п. А можно собраться вместе с друзьями и дозвониться один раз, затем просто передавать трубку друг другу для разговора. Телефон в данном случае будет выступать в качестве пула соединений. Вернемся к нашей модели. Промежуточный сервер тоже будет выступать в качестве пула соединений. Более того, если к нему будут обращаться несколько клиентских приложений (несколько друзей), использующих одинаковую базу данных и параметры авторизации (один человек на другом конце земного шара), то выигрыш времени будет еще более заметным.
При создании подключения с использованием поставщиков данных .NET автоматически создается пул соединений. При вызове метода Close соединения не разрывается, а по умолчанию помещается в пул. В течение 60 секунд соединение остается открытым, и если оно не используется повторно, поставщик данных закрывает его. Если же по каким-либо причинам нам необходимо закрывать соединение, не помещая его в пул, в строке соединения СonnectionString нужно вставить дополнительный параметр. Для поставщика OLE DB:
OLE DB Services=-4;
Для поставщика SQL Server:
Pooling=False;
Теперь при вызове метода Close соединение действительно будет разорвано.
Поставщик данных Microsoft SQL Server предоставляет также дополнительные параметры управления пулом соединений (таблица 4.4).
| Параметр | Описание | Значение по умолчанию |
|---|---|---|
Connection Lifetime |
Время (в сек.), по истечении которого открытое соединение будет закрыто и удалено из пула. Сравнение времени создания соединения с текущим временем проводится при возвращении соединения в пул. Если соединение не запрашивается, а время, заданное параметром, истекло, соединение закрывается. Значение 0 означает, что соединение будет закрыто по истечении максимального предусмотренного тайм-аута (60 сек.) | 0 |
Enlist |
Необходимость связывания соединения с контекстом текущей |
True |
Max Pool Size |
Максимальное число соединений в пуле. При исчерпании свободных соединений клиентское приложение будет ждать освобождения свободного соединения | 100 |
Min Pool Size |
Минимальное число соединений в пуле в любой момент времени | 0 |
Pooling |
Использование пула соединений | True |
Для задания значения параметра, отличного от принятого по умолчанию, следует явно включить его в строку ConnectionString.
Для слежения за процессом подключения к серверу и организацией пула соединений воспользуемся утилитой
(рис 4.14) Подключение к серверу Далее появляется окно Trace Properties (Свойства трассировки), в котором можно задать название трассировки, а также расположение файла для сохранения (галочка "Save to file") (рис. 4.15).
(рис 4.15) Свойства трассировкиНажимаем кнопку "Run" для начала работы. Появляется окно, в котором будет записываться все обращения к серверу. Запускаем приложение ExceptionsSQL, вводим данные для аутентификации и нажимаем кнопку "Соединение" - SQL Profiler немедленно зафиксирует обращение (рис. 4.16).
(рис 4.16) Окно трассировки после подключения к серверу Соединение по умолчанию помещается в пул, в окне трассировки мы не видим его разрыва - записи "Audit Logout". Ее можно увидеть, завершив работу с приложением ExceptionsSQL (рис. 4.17).
(рис 4.17) Окно трассировки после завершения работы с приложением "ExceptionsSQL"Открываем проект ExceptionsSQL в среде Visual Studio .NET, изменим строку соединения - отключим необходимость создания пула. Строка ConnectionString теперь будет выглядеть так (добавлен параметр "Pooling"):
conn.ConnectionString = "initial catalog=" + txtInitialCatalog.Text + ";" + "user id=" + txtUserID.Text + ";" + "password=" + txtPassword.Text + ";" + "data source=" + txtDataSource.Text + ";" + "workstation id=9E0D682EA8AE448;persist security info=True;Pooling=False";
Теперь при соединении с сервером соединение будет разрываться без помещения в пул - запись "Audit Logout" будет появляться сразу же (рис. 4.18):
(рис 4.18) Окно трассировки после подключения к серверу без создания пула соединений Помещение соединений в пул, включенное по умолчанию, - одно из средств повышения производительности приложений. Не следует без надобности отключать эту возможность.
Среда Microsoft SQL Server предоставляет средства разделенного управления объектами сервера. Для доступа используются два режима аутентификации: режим аутентификации Windows (Windows Authentication) и режим смешанной аутентификации (Mixed Mode Authentication). При установке первый режим предлагается по умолчанию, поэтому, скорее всего, ваш сервер сконфигурирован с его использованием (рис. 4.1):
(рис 4.1) Режим аутентификации Windows предлагаемый по умолчанию при установкеВ этом случае аутентификация пользователя осуществляется операционной системой Windows. Затем SQL Server использует аутентификацию операционной системы для определения уровня доступа. При подключении в окне "Свойства связи с данными" мы также указывали этот режим (рис. 4.2):
(рис 4.2) Режим аутентификации Windows в окне "Свойства связи с данными"Смешанный режим позволяет проводить аутентификацию пользователя как средствами операционной системы, так и с применением учетных записей Microsoft SQL Server. Для включения этого режима запускаем SQL Server Enterprise Manager, на узле локального сервера щелкаем правой кнопкой и выбираем пункт меню "Свойства". В появившемся окне "SQL Server Properties" переходим на вкладку "Security", устанавливаем переключатель в положение "SQL Server and Windows" (рис. 4.3).
(рис 4.3) Включение режима смешанной аутентификацииПосле подтверждения изменений закрываем окно свойств. Раскрываем узел "Security" текущего сервера, выделяем объект "Logins". В нем мы видим две записи - "BULTIN\Администраторы" и "sa". Первая из них предназначена для аутентификации учетных записей операционной системы. Вторая - "sa" (
(рис 4.4) Установка пароля на учетной записи "sa" Займемся теперь подключением к заданной базе данных, например Northwind, от имени учетной записи "sa". Создайте новое Windows-приложение, назовите его "VisualSQLUser_sa". Перетаскиваем на форму элемент управления DataGrid, его свойству Dock устанавливаем значение "Fill". В окне Toolbox переходим на вкладку Data и дважды щелкаем на объекте SqlDataAdapter. В появившемся мастере создаем новое подключение. В окне "Свойства связи с данными" указываем название локального сервера (local), имя пользователя (sa) и пароль (12345), а также базу данных Northwind (рис. 4.5):
(рис 4.5) Окно "Свойство связи с данными". Приложение VisualSQLUser_saДополнительно мы установили галочку "Разрешить сохранение пароля". При этом его значение (12345) будет сохранено в виде текста в строке connectionString. Пока мы вынуждены это сделать - интерфейс нашего приложения не предусматривает возможность ввода пароля в момент подключения. Завершаем работу мастера "Data
(рис 4.6) Диалоговое окно сохранения пароля На панели компонент формы выделяем объект DataAdapter, переходим в его окно Properties и нажимаем на ссылку "Generate dataset". Оставляем название объекта DataSet, предлагаемое по умолчанию. В конструкторе формы заполняем объект DataSet, а также определяем источник данных для элемента DataGrid:
public Form1()
{
InitializeComponent();
sqlDataAdapter1.Fill(dataSet11);
dataGrid1.DataSource = dataSet11.Tables[0].DefaultView;
}
Запускаем приложение. На форму выводятся записи таблицы Customers (рис. 4.7):
(рис 4.7) Готовое приложение VisualSQLUser_saВ программном обеспечении к курсу вы найдете приложение VisualSQL User_sa (Code\Glava2\ VisualSQLUser_sa).
Сделаем точно такое же приложение без использования визуальных средств студии. Создайте новый Windows-проект, назовите его "ProgrammSQLUser_sa". Добавляем на форму элемент управления DataGrid, его свойству Dock устанавливаем значение "Fill". Подключаем пространство имен для работы с базой:
using System.Data.SqlClient;
В классе формы создаем строки connectionString и commandText:
string connectionString = "workstation id=9E0D682EA8AE448; user id=sa;data source=\"(local)\";" + "persist security info=True;initial catalog=Northwind;password=12345"; string commandText = "SELECT * FROM Customers";
В конструкторе формы создаем все объекты ADO .NET:
public Form1()
{
InitializeComponent();
SqlConnection conn = new SqlConnection();
conn.ConnectionString = connectionString;
SqlDataAdapter dataAdapter = new SqlDataAdapter(commandText, conn);
DataSet ds = new DataSet();
dataAdapter.Fill(ds);
dataGrid1.DataSource = ds.Tables[0].DefaultView;
conn.Close();
}
В программном обеспечении к курсу вы найдете приложение Programm SQLUser_sa (Code\Glava2\ProgrammSQLUser_sa).
В отличие от подключений к базе данных Microsoft Access здесь мы не встретили никаких сложностей. Вкладка "Подключение" в окне "Свойства связи с данными" действительно предоставляет все средства для подключения к базе данных Microsoft SQL Server. Для аутентификации пользователя достаточно указать его имя и пароль.
Класс Connection поддерживает несколько событий, позволяющих отслеживать статус соединения и получать уведомляющие сообщения для экземпляра этого класса. Описание событий приводится в таблице 4.1.
| Событие | Описание |
|---|---|
Disposed |
Возникает при вызове метода Dispose экземпляра класса |
InfoMessage |
Возникает при получении информационного сообщения от поставщика данных |
StateChange |
Возникает при открытии или закрытии соединения. Поддерживается информация о текущем и исходном состояниях |
При вызове метода Dispose объекта Connection происходит освобождение занимаемых ресурсов и сборка мусора. При этом неявно вызывается метод Close.
Рассмотрим применение события StateChange и обработчик события Disposed. Создайте новое Windows-приложение и назовите его "ConnectionEventsSQL". Свойству Size формы устанавливаем значение "600;300". Помещаем на форму элемент управления DataGrid, его свойству Dock устанавливаем значение "Fill". Добавляем элемент Panel, его свойству Dock устанавливаем значение "Bottom". На панели размещаем две надписи и одну кнопку, устанавливая следующие их свойства:
| label1, свойство | Значение |
|---|---|
| Location | 8; 8 |
| Size | 208; 80 |
| Text |
| labe2, свойство | Значение |
|---|---|
| Location | 232; 8 |
| Size | 208; 80 |
| Text |
| button1, свойство | Значение |
|---|---|
| Name | btnFill |
| Location | 488; 40 |
| Text | Заполнить |
Подключаем пространство имен для работы с базой:
using System.Data.SqlClient;
В классе формы создаем строки connectionString и commandText:
string connectionString = "workstation id=9E0D682EA8AE448; packet size=4096;integrated security=SSPI;data source=\"(local)\"; persist security info=False;initial catalog=Northwind"; string commandText = "SELECT * FROM Customers";
Объекты ADO .NET будем создавать в обработчике события Click кнопки "btnFill":
private void btnFill_Click(object sender, System.EventArgs e)
{
SqlConnection conn = new SqlConnection();
conn.ConnectionString = connectionString;
//Делегат EventHandler связывает метод-обработчик conn_Disposed
//с событием Disposed объекта conn
conn.Disposed+=new EventHandler(conn_Disposed);
//Делегат StateChangeEventHandler связывает метод-обработчик
//conn_StateChange с событием StateChange объекта conn
conn.StateChange+= new StateChangeEventHandler(conn_StateChange);
SqlDataAdapter dataAdapter = new SqlDataAdapter(commandText, conn);
DataSet ds = new DataSet();
dataAdapter.Fill(ds);
dataGrid1.DataSource = ds.Tables[0].DefaultView;
//Метод Dispose, включающий в себя метод Close,
//разрывает соединение и освобождает ресурсы.
conn.Dispose();
}
Не забывайте про возможности IntelliSense - как всегда, для создания методов-обработчиков дважды нажимаем клавишу TAB (рис. 4.8):
(рис 4.8) Автоматическое создание методов-обработчиковВ методе conn_Disposed просто выводим текстовое сообщение в надпись "label2":
private void conn_Disposed(object sender, EventArgs e)
{
label2.Text+="Событие Dispose";
}
При необходимости в этом методе могут быть определены соответствующие события. В методе conn_StateChange будем получать информацию о текущем и исходном состояниях:
private void conn_StateChange(object sender, StateChangeEventArgs e)
{
label1.Text+="\nИсходное состояние: "+e.OriginalState.ToString()
+ "\nТекущее состояние: "+ e.CurrentState.ToString();
}
Запускаем приложение. До открытия соединения состояние объекта conn было закрытым. В момент открытия текущим состоянием становится открытое, а предыдущим - закрытое. Этому соответствуют первые две строки, выведенные в надпись (рис. 4.9):
(рис 4.9) Готовое приложение ConnectionEventsSQLПосле закрытия соединения (вызова метода Dispose ) текущим состоянием становится закрытое, а предыдущим - открытое. Этому соответствуют последние две строки, выводимые в надпись.
Конечно, в таком предельно простом приложении и так ясен статус соединения. Но сама идея может применяться в любых, сколь угодно сложных приложениях, когда необходимо определять статус одного из нескольких подключений.
В программном обеспечении к курсу вы найдете приложение Connection EventsSQL (Code\Glava2\ ConnectionEventsSQL).
Создадим теперь аналогичное приложение, использующее базу данных Microsoft Access. Для того чтобы не терять время на создание пользовательского интерфейса, скопируйте папку приложения Connection EventsSQL и назовите ее "ConnectionEventsMDB". Перейдем к редактированию кода. Подключаем пространство имен для работы с базой данных:
using System.Data.OleDb;
В классе формы создаем строки connectionString и commandText:
string connectionString = @"Provider=""Microsoft.Jet.OLEDB.4.0" "; Data Source=""E:\Program Files\Microsoft Visual Studio .NET 2003\Crystal Reports\Samples\Database\xtreme.mdb"";User ID=Admin;Jet OLEDB:Encrypt Database=False"; string commandText = "SELECT * FROM Customer";
Здесь мы снова будем подключаться к базе данных xtreme.mdb. Обработчик события Click кнопки "btnFill" примет следующий вид:
private void btnFill_Click(object sender, System.EventArgs e)
{
OleDbConnection conn = new OleDbConnection();
conn.ConnectionString = connectionString;
//Делегат EventHandler связывает метод-обработчик conn_Disposed
//с событием Disposed объекта conn
conn.Disposed+=new EventHandler(conn_Disposed);
//Делегат StateChangeEventHandler связывает метод-обработчик
//conn_StateChange с событием StateChange объекта conn
conn.StateChange+= new StateChangeEventHandler(conn_StateChange);
OleDbDataAdapter dataAdapter = new OleDbDataAdapter(commandText, conn);
DataSet ds = new DataSet();
dataAdapter.Fill(ds);
dataGrid1.DataSource = ds.Tables[0].DefaultView;
//Метод Dispose, включающий в себя метод Close,
//разрывает соединение и освобождает ресурсы.
conn.Dispose();
}
Обработчики conn_Disposed и conn_StateChange будут иметь в точности такой же вид. Запускаем приложение - на форму снова выводится статус соединения (рис. 4.10):
(рис 4.10) Готовое приложение ConnectionEventsMDBВ программном обеспечении к курсу вы найдете приложение Connection EventsMDB (Code\Glava2\ ConnectionEventsMDB).
Подключение к базе данных представляет собой одно из слабых мест в работе программы. В силу самых разных причин клиент может не получить доступ к базе данных. Поэтому при создании приложения следует обязательно включать обработку исключений и возможность предоставления пользователю информации о них.
Для получения специализированных сообщений при возникновении ошибок подключения к базе данных Microsoft SQL Server используются классы SqlException и SqlErro r. Объекты этих классов можно применять для перехвата номеров ошибок, возвращаемых базой данных (таблица 4.2):
| Номер ошибки | Описание |
|---|---|
| 17 | Неверное имя сервера |
| 4060 | Неверное название базы данных |
| 18456 | Неверное имя пользователя или пароль |
Дополнительно вводятся уровни ошибок SQL Server, позволяющие охарактеризовать причину проблемы и ее сложность (таблица 4.3):
| Интервал возвращаемых значений | Описание | Действие |
|---|---|---|
| 11-16 | Ошибка, созданная пользователем | Пользователь должен повторно ввести верные данные |
| 17-19 | Ошибки программного обеспечения или оборудования | Пользователь может продолжать работу, но некоторые запросы будут недоступны. Соединение остается открытым |
| 20-25 | Ошибки программного обеспечения или оборудования | Сервер закрывает соединение. Пользователь должен открыть его снова |
Создайте новое Windows-приложение и назовите его "ExceptionsSQL". Свойству Size формы устанавливаем значение "600;380". Добавляем на форму элемент управления DataGrid, его свойству Dock устанавливаем значение "Fill". Перетаскиваем элемент Panel, определяем следующие его свойства:
| panel1, свойство | Значение |
|---|---|
| Dock | Right |
| Location | 392; 0 |
| Size | 200; 346 |
На панели размещаем четыре текстовых поля, надпись и кнопку:
| textBox1, свойство | Значение |
|---|---|
| Name | txtDataSource |
| Location | 8; 8 |
| Size | 184; 20 |
| Text | Введите название сервера |
| textBox2, свойство | Значение |
|---|---|
| Name | txtInitialCatalog |
| Location | 8; 40 |
| Size | 184; 20 |
| Text | Введите название базы данных |
| textBox3, свойство | Значение |
|---|---|
| Name | txtUserID |
| Location | 8; 72 |
| Size | 184; 20 |
| Text | Введите имя пользователя |
| textBox4, свойство | Значение |
|---|---|
| Name | txtPassword |
| Location | 8; 104 |
| Size | 184; 20 |
| Text | Введите |
| label1, свойство | Значение |
|---|---|
| Location | 16; 136 |
| Size | 176; 160 |
| Text |
| button1, свойство | Значение |
|---|---|
| Name | btnConnect |
| Location | 56; 312 |
| Size | 96; 23 |
| Text | Соединение |
Интерфейс приложения готов. Подключаем пространство имен для работы с базой данных:
using System.Data.SqlClient;
Объекты ADO .NET и весь блок обработки исключений помещаем в обработчик кнопки "Соединение":
private void btnConnect_Click(object sender, System.EventArgs e)
{
SqlConnection conn = new SqlConnection();
label1.Text = "";
try
{
//conn.ConnectionString = "workstation id=9E0D682EA8AE448;data source=\"(local)
//\";" + "persist security info=True;initial catalog=Northwind;
//user id=sa;password=12345";
//Строка ConnectionString в качестве параметров
//будет передавать значения, введенные в текстовые поля:
conn.ConnectionString =
"initial catalog=" + txtInitialCatalog.Text + ";" +
"user id=" + txtUserID.Text + ";" +
"password=" + txtPassword.Text + ";" +
"data source=" + txtDataSource.Text + ";" +
"workstation id=9E0D682EA8AE448;persist security info=True;";
SqlDataAdapter dataAdapter = new SqlDataAdapter("SELECT * FROM
Customers", conn);
DataSet ds = new DataSet();
conn.Open();
dataAdapter.Fill(ds);
dataGrid1.DataSource = ds.Tables[0].DefaultView;
}
catch (SqlException OshibkiSQL)
{
foreach (SqlError oshibka in OshibkiSQL.Errors)
{
//Свойство Number объекта oshibka возвращает
//номер ошибки SQL Server
switch (oshibka.Number)
{
case 17:
label1.Text += "\nНеверное имя сервера!";
break;
case 4060:
label1.Text += "\nНеверное имя базы данных!";
break;
case 18456:
label1.Text += "\nНеверное имя пользователя или пароль!";
break;
}
//Свойство Class объекта oshibka возвращает
//уровень ошибки SQL Server,
//а свойство Message - уведомляющее сообщение
label1.Text +="\n"+oshibka.Message + "
Уровень ошибки SQL Server: " + oshibka.Class; }
}
//Отлавливаем прочие возможные ошибки:
catch (Exception ex)
{
label1.Text += "\nОшибка подключения: " + ex.Message;
}
finally
{
conn.Dispose();
}
}
Закомментированная строка подключения содержит обычное перечисление параметров. При отладке приложения будет легче сначала добиться наличия подключения, а затем осуществлять привязку параметров, вводимых в текстовые поля. Запускаем приложение. При вводе неверных параметров в надпись выводятся соответствующие сообщения, а при правильных параметрах элемент DataGrid отображает данные (рис. 4.11):
(рис 4.11) Готовое приложение ExceptionsSQLВ программном обеспечении к курсу вы найдете приложение Exceptions SQL (Code\Glava2\ ExceptionsSQL).
Скопируйте папку приложения ExceptionsSQL и назовите ее "ExceptionsMDB". Удаляем с панели на форме имеющиеся текстовые поля и добавляем три новых:
| textBox1, свойство | Значение |
|---|---|
| Name | txtDataBasePassword |
| Location | 8; 16 |
| Size | 184; 20 |
| Text | Введите пароль базы данных |
| textBox2, свойство | Значение |
|---|---|
| Name | txtUserID |
| Location | 8; 48 |
| Size | 184; 20 |
| Text | Введите имя пользователя |
| textBox3, свойство | Значение |
|---|---|
| Name | TxtPassword |
| Location | 8; 80 |
| Size | 184; 20 |
| Text | Введите пароль пользователя |
Изменяем пространство имен для работы с базой данных:
using System.Data.OleDb;
Обработчик кнопки "Соединение" будет выглядеть так:
private void btnConnect_Click(object sender, System.EventArgs e)
{
OleDbConnection conn = new OleDbConnection();
label1.Text = "";
try
{
// conn.ConnectionString = @"Provider=""Microsoft.Jet.OLEDB.4.0"";
//Data Source=""D:\Uchebnik\Code\Glava2\BDwithUsersP.mdb"";
Jet OLEDB:System database=""D:\Uchebnik\Code\Glava2\BDWorkFile.mdw"";
User ID=Adonetuser;Password=12345;Jet OLEDB:Database Password=98765;";
//Строка ConnectionString в качестве параметров
//будет передавать значения, введенные в текстовые поля:
conn.ConnectionString =
"Jet OLEDB:Database Password=" + txtDataBasePassword.Text
+ ";" + "User ID=" + txtUserID.Text + ";" +
"password=" + txtPassword.Text + ";" +
@"Provider=""Microsoft.Jet.OLEDB.4.0"";Data
Source=""D:\Uchebnik\Code\Glava2\BDwithUsersP.mdb"";
Jet OLEDB:System database=""D:\Uchebnik\Code\Glava
\BDWorkFile.mdw"";";
OleDbDataAdapter dataAdapter =
new OleDbDataAdapter("SELECT * FROM Туристы", conn);
DataSet ds = new DataSet();
conn.Open();
dataAdapter.Fill(ds);
dataGrid1.DataSource = ds.Tables[0].DefaultView;
}
catch (OleDbException oshibka)
{
//Пробегаем по всем ошибкам
for (int i=0; i < oshibka.Errors.Count; i++)
{
label1.Text+= "Номер ошибки " + i
+ "\n" + "Сообщение: " +
oshibka.Errors[i].Message + "\n" +
"Номер ошибки NativeError: " +
oshibka.Errors[i].NativeError + "\n" +
"Источник: " + oshibka.Errors[i].Source +
"\n" + "Номер SQLState: " +
oshibka.Errors[i].SQLState + "\n";
}
}
//Отлавливаем прочие возможные ошибки:
catch (Exception ex)
{
label1.Text += "\nОшибка подключения: " +
ex.Message;
}
finally
{
conn.Dispose();
}
}
Запускаем приложение (рис. 4.12). Свойство Message возвращает причину ошибки на русском языке, поскольку установлена русская версия Microsoft Office 2003. Свойство NativeError (внутренняя ошибка) возвращает номер исключения, генерируемый самим источником данных. Вместе или по отдельности со свойством SQL State их можно использовать для создания переключателя, предоставляющего пользователю расширенную информацию (мы это делали в приложении ExceptionsSQL) .
(рис 4.12) Готовое приложение ExceptionsMDBКроме обработки исключений, здесь следует обратить внимание на интерфейс, предоставляющий возможность пользователю вводить сведения своей учетной записи. Теперь в целях безопасности приложения не нужно включать пароль в код при использовании мастеров, поскольку строка соединения будет генерироваться динамически. Разумеется, ваше приложение может иметь другой интерфейс - например, окно соединения будет появляться в дочерней форме.
В программном обеспечении к курсу вы найдете приложение Exceptions MDB (Code\Glava2\ ExceptionsMDB).
Подключение к базе данных требует затрат времени - в самом деле, необходимо установить соединение по каналам связи, пройти аутентификацию и лишь после этого можно выполнять запросы и получать данные. Клиентское приложение, взаимодействующее с базой данных и закрывающее каждый раз соединение при помощи метода Close, будет не слишком производительным: значительная часть времени и ресурсов будет тратиться на установку повторного соединения. А что, если использовать трехуровневую модель, при которой клиентское соединение будет взаимодействовать с базой данных через промежуточный сервер? В этой модели клиентское приложение открывает соединение через промежуточный сервер (рис. 4.13, А). После завершения работы соединение закрывается приложением, но промежуточный сервер продолжает удерживать его в течение заданного промежутка времени, например, 60 секунд. По истечении этого времени промежуточный сервер закрывает соединение с базой данных (рис. 4.13, Б). Если в течение этой минуты, например, после 35 секунд, клиентское приложение снова требует связи с базой данных, то сервер просто предоставляет уже готовое соединение, причем после завершения работы обнуляет счет времени и готов снова минуту ждать обращения (рис. 4.13, В).
(рис 4.13) Трехуровневая модель соединения с базой данных. А - открытие соединения, начало отсчета, Б - Закрытие соединения промежуточным сервером по истечении минуты, В - Обращение клиентского приложения и предоставление сервером соединения в течении минуты ожидания В результате использования этой модели сокращается время, необходимое для установки связи с удаленной базой данных. Можно провести аналогию со следующей ситуацией: представьте, что вам и вашим друзьям нужно поговорить с одним и тем же человеком на другом конце земного шара. Вы можете звонить по отдельности и потратить достаточно много времени на то, чтобы дозвониться до человека, дождаться, пока его позовут к телефону, и т.п. А можно собраться вместе с друзьями и дозвониться один раз, затем просто передавать трубку друг другу для разговора. Телефон в данном случае будет выступать в качестве пула соединений. Вернемся к нашей модели. Промежуточный сервер тоже будет выступать в качестве пула соединений. Более того, если к нему будут обращаться несколько клиентских приложений (несколько друзей), использующих одинаковую базу данных и параметры авторизации (один человек на другом конце земного шара), то выигрыш времени будет еще более заметным.
При создании подключения с использованием поставщиков данных .NET автоматически создается пул соединений. При вызове метода Close соединения не разрывается, а по умолчанию помещается в пул. В течение 60 секунд соединение остается открытым, и если оно не используется повторно, поставщик данных закрывает его. Если же по каким-либо причинам нам необходимо закрывать соединение, не помещая его в пул, в строке соединения СonnectionString нужно вставить дополнительный параметр. Для поставщика OLE DB:
OLE DB Services=-4;
Для поставщика SQL Server:
Pooling=False;
Теперь при вызове метода Close соединение действительно будет разорвано.
Поставщик данных Microsoft SQL Server предоставляет также дополнительные параметры управления пулом соединений (таблица 4.4).
| Параметр | Описание | Значение по умолчанию |
|---|---|---|
Connection Lifetime |
Время (в сек.), по истечении которого открытое соединение будет закрыто и удалено из пула. Сравнение времени создания соединения с текущим временем проводится при возвращении соединения в пул. Если соединение не запрашивается, а время, заданное параметром, истекло, соединение закрывается. Значение 0 означает, что соединение будет закрыто по истечении максимального предусмотренного тайм-аута (60 сек.) | 0 |
Enlist |
Необходимость связывания соединения с контекстом текущей |
True |
Max Pool Size |
Максимальное число соединений в пуле. При исчерпании свободных соединений клиентское приложение будет ждать освобождения свободного соединения | 100 |
Min Pool Size |
Минимальное число соединений в пуле в любой момент времени | 0 |
Pooling |
Использование пула соединений | True |
Для задания значения параметра, отличного от принятого по умолчанию, следует явно включить его в строку ConnectionString.
Для слежения за процессом подключения к серверу и организацией пула соединений воспользуемся утилитой
(рис 4.14) Подключение к серверу Далее появляется окно Trace Properties (Свойства трассировки), в котором можно задать название трассировки, а также расположение файла для сохранения (галочка "Save to file") (рис. 4.15).
(рис 4.15) Свойства трассировкиНажимаем кнопку "Run" для начала работы. Появляется окно, в котором будет записываться все обращения к серверу. Запускаем приложение ExceptionsSQL, вводим данные для аутентификации и нажимаем кнопку "Соединение" - SQL Profiler немедленно зафиксирует обращение (рис. 4.16).
(рис 4.16) Окно трассировки после подключения к серверу Соединение по умолчанию помещается в пул, в окне трассировки мы не видим его разрыва - записи "Audit Logout". Ее можно увидеть, завершив работу с приложением ExceptionsSQL (рис. 4.17).
(рис 4.17) Окно трассировки после завершения работы с приложением "ExceptionsSQL"Открываем проект ExceptionsSQL в среде Visual Studio .NET, изменим строку соединения - отключим необходимость создания пула. Строка ConnectionString теперь будет выглядеть так (добавлен параметр "Pooling"):
conn.ConnectionString = "initial catalog=" + txtInitialCatalog.Text + ";" + "user id=" + txtUserID.Text + ";" + "password=" + txtPassword.Text + ";" + "data source=" + txtDataSource.Text + ";" + "workstation id=9E0D682EA8AE448;persist security info=True;Pooling=False";
Теперь при соединении с сервером соединение будет разрываться без помещения в пул - запись "Audit Logout" будет появляться сразу же (рис. 4.18):
(рис 4.18) Окно трассировки после подключения к серверу без создания пула соединений Помещение соединений в пул, включенное по умолчанию, - одно из средств повышения производительности приложений. Не следует без надобности отключать эту возможность.
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.