Технология Microsoft ADO .NET

Подключение к базе данных Microsoft SQL Server

Разбить на страницы
Показывать лекцию целиком

Подключение к базе данных Microsoft SQL Server

Подключение к базе данных Microsoft SQL Server с разделенным доступом

Среда 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" (system administrator) - представляет собой учетную запись администратора сервера, по умолчанию она конфигурируется без пароля. Для его создания щелкаем правой кнопкой мыши на записи, в появившемся меню выбираем пункт "Свойства". В поле "Password" окна "SQL Server Login Properties" вводим пароль "12345" и подтверждаем его (рис. 4.4):

(рис 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 Adapter Configuration Wizard", настраивая извлечение всех записей из таблицы Customers. В последнем шаге мы снова соглашаемся сохранить пароль в виде текста (рис. 4.6).

(рис 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

Класс Connection поддерживает несколько событий, позволяющих отслеживать статус соединения и получать уведомляющие сообщения для экземпляра этого класса. Описание событий приводится в таблице 4.1.

События объекта Connection
Событие Описание
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):

Ошибки SQL Server
Номер ошибки Описание
17 Неверное имя сервера
4060 Неверное название базы данных
18456 Неверное имя пользователя или пароль

Дополнительно вводятся уровни ошибок SQL Server, позволяющие охарактеризовать причину проблемы и ее сложность (таблица 4.3):

Уровни ошибок SQL Server
Интервал возвращаемых значений Описание Действие
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 Введите парольДля скрывания пароля при вводе можно в свойстве "PasswordChar" текстового поля ввести заменяющий символ, например, звездочку ("*").
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).

Работа с пулом соединений. Microsoft SQL Profiler

Подключение к базе данных требует затрат времени - в самом деле, необходимо установить соединение по каналам связи, пройти аутентификацию и лишь после этого можно выполнять запросы и получать данные. Клиентское приложение, взаимодействующее с базой данных и закрывающее каждый раз соединение при помощи метода 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).

Параметры пула соединения поставщика MS SQL Server
Параметр Описание Значение по умолчанию
Connection Lifetime Время (в сек.), по истечении которого открытое соединение будет закрыто и удалено из пула. Сравнение времени создания соединения с текущим временем проводится при возвращении соединения в пул. Если соединение не запрашивается, а время, заданное параметром, истекло, соединение закрывается. Значение 0 означает, что соединение будет закрыто по истечении максимального предусмотренного тайм-аута (60 сек.) 0
Enlist Необходимость связывания соединения с контекстом текущей транзакцииОписание транзакций см. в лекции 7. потока True
Max Pool Size Максимальное число соединений в пуле. При исчерпании свободных соединений клиентское приложение будет ждать освобождения свободного соединения 100
Min Pool Size Минимальное число соединений в пуле в любой момент времени 0
Pooling Использование пула соединений True

Для задания значения параметра, отличного от принятого по умолчанию, следует явно включить его в строку ConnectionString.

Для слежения за процессом подключения к серверу и организацией пула соединений воспользуемся утилитой ProfilerПодробное описание работы с этой утилитой вы можете найти здесь: http://www.intuit.ru/department/database/sqlserver2000/35/sqlserver2000_35.html , входящей в пакет Microsoft SQL Server 2000. Переходим в меню "Пуск" к группе Microsoft SQL Server и запускаем утилиту. В появившемся окне программы переходим "File \ New \ Trace" (или используем сочетание клавиш Ctrl+N). Появляется подключение к серверу. Это окно нам уже знакомо по работе с программой Query Analyzer. На этот раз подключимся к серверу от имени администратора "sa" (рис. 4.14):

(рис 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

Подключение к базе данных Microsoft SQL Server с разделенным доступом

Среда 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" (system administrator) - представляет собой учетную запись администратора сервера, по умолчанию она конфигурируется без пароля. Для его создания щелкаем правой кнопкой мыши на записи, в появившемся меню выбираем пункт "Свойства". В поле "Password" окна "SQL Server Login Properties" вводим пароль "12345" и подтверждаем его (рис. 4.4):

(рис 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 Adapter Configuration Wizard", настраивая извлечение всех записей из таблицы Customers. В последнем шаге мы снова соглашаемся сохранить пароль в виде текста (рис. 4.6).

(рис 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

Класс Connection поддерживает несколько событий, позволяющих отслеживать статус соединения и получать уведомляющие сообщения для экземпляра этого класса. Описание событий приводится в таблице 4.1.

События объекта Connection
Событие Описание
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):

Ошибки SQL Server
Номер ошибки Описание
17 Неверное имя сервера
4060 Неверное название базы данных
18456 Неверное имя пользователя или пароль

Дополнительно вводятся уровни ошибок SQL Server, позволяющие охарактеризовать причину проблемы и ее сложность (таблица 4.3):

Уровни ошибок SQL Server
Интервал возвращаемых значений Описание Действие
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 Введите парольДля скрывания пароля при вводе можно в свойстве "PasswordChar" текстового поля ввести заменяющий символ, например, звездочку ("*").
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).

Работа с пулом соединений. Microsoft SQL Profiler

Подключение к базе данных требует затрат времени - в самом деле, необходимо установить соединение по каналам связи, пройти аутентификацию и лишь после этого можно выполнять запросы и получать данные. Клиентское приложение, взаимодействующее с базой данных и закрывающее каждый раз соединение при помощи метода 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).

Параметры пула соединения поставщика MS SQL Server
Параметр Описание Значение по умолчанию
Connection Lifetime Время (в сек.), по истечении которого открытое соединение будет закрыто и удалено из пула. Сравнение времени создания соединения с текущим временем проводится при возвращении соединения в пул. Если соединение не запрашивается, а время, заданное параметром, истекло, соединение закрывается. Значение 0 означает, что соединение будет закрыто по истечении максимального предусмотренного тайм-аута (60 сек.) 0
Enlist Необходимость связывания соединения с контекстом текущей транзакцииОписание транзакций см. в лекции 7. потока True
Max Pool Size Максимальное число соединений в пуле. При исчерпании свободных соединений клиентское приложение будет ждать освобождения свободного соединения 100
Min Pool Size Минимальное число соединений в пуле в любой момент времени 0
Pooling Использование пула соединений True

Для задания значения параметра, отличного от принятого по умолчанию, следует явно включить его в строку ConnectionString.

Для слежения за процессом подключения к серверу и организацией пула соединений воспользуемся утилитой ProfilerПодробное описание работы с этой утилитой вы можете найти здесь: http://www.intuit.ru/department/database/sqlserver2000/35/sqlserver2000_35.html , входящей в пакет Microsoft SQL Server 2000. Переходим в меню "Пуск" к группе Microsoft SQL Server и запускаем утилиту. В появившемся окне программы переходим "File \ New \ Trace" (или используем сочетание клавиш Ctrl+N). Появляется подключение к серверу. Это окно нам уже знакомо по работе с программой Query Analyzer. На этот раз подключимся к серверу от имени администратора "sa" (рис. 4.14):

(рис 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) Окно трассировки после подключения к серверу без создания пула соединений

Помещение соединений в пул, включенное по умолчанию, - одно из средств повышения производительности приложений. Не следует без надобности отключать эту возможность.

Вернуться к учебному плану