- •Лекция 4 «Работа с бд Microsoft sql Server без разрыва соединения (связный уровень ado.Net)»
- •1. Создание соединения с источником данных
- •Конструкторы
- •Свойства
- •События
- •2. Работа с базой данных с помощью sql-запросов. Выборка, добавление, удаление и обновление данных
- •Конструкторы
- •Свойства
- •Сравнение DataReader и DataSet:
- •Чтение данных из DataReader:
- •Цикл по всем записям: Для перебора и вывода на консоль всех записей в DataReader, вы можете использовать цикл while, как показано в следующем примере кода:
- •Использование DataSets и DataReaders:
- •4. Отображение информации из базы данных с помощью элементов управления ListBox, ComboBox, ListView, DataGridView, DataTable.
Использование DataSets и DataReaders:
DataSet |
DataReader |
Создание связей базы данных |
Создание связей базы данных |
Сохранение в DataAdapter |
Открыть соединение с базой данных |
Заполнение DataSet с помощью метода Fill() |
Сохранить запрос в SqlCommand |
Создать объект DataView |
Заполнение DataReader с помощью метода ExecuteReader () |
Привязка DataView к списку управления с привязкой |
Вызвать Read для каждой записи, и Get для каждого поля |
|
Отображение данных вручную |
|
Закрыть DataReader и соединение |
Общая процедура доступа к базам данных из ADO.NET отличается в зависимости от того, будет использоваться DataSet или DataReader:
Использование DataSet |
Использование DataReader |
1. Подключение к базе данных с помощью SqlConnection или OleDbConnection |
1. Подключение к базе данных с помощью SqlConnection или OleDbConnection. |
2. Сохранение запроса к базе данных в объектах SqlDataAdapter или OleDbDataAdapter. |
2. Открыть связи с помощью метода Open. |
3. Заполнение DataSet из DataAdapter с помощью Fill. |
3. Сохранение запроса к базе данных в объекты SqlCommand или OleDbCommand. |
4. Установление нового DataView для необходимой таблицы. |
4. Заполнение DataReader из Command с помощью метода ExecuteReader(). |
5. Привязка серверного элемента управления такого как DataGrid для DataView. |
5. Вызвать методы Read и Get объекта DataReader для чтения данных. |
|
6. Отображение данных вручную. |
|
7. Закрыть DataReader и соединение. |
Получение множества наборов результатов с помощью объектов чтения данных.
Объекты чтения данных могут получать от одного объекта команды множество наборов результатов (из разных таблиц БД). Например, чтобы получить все строки таблицы «Друзья» и все строки таблицы «Информация о друзьях», можно указать оба соответствующих SQL-оператора, используя в качестве разделителя точку с запятой (если имя поля состоит из нескольких слов, то в SQL-операторе его нужно заключать в квадратные скобки). Получив объект чтения данных, можно переходить от одного результирующего набора к другому с помощью метода NextResult(). При этом возвращение к первому набору происходит автоматически:
/////// Получение двух наборов результатов:
cn.Open();
string theSQL = "Select * From Друзья; Select * From [Информация о друзьях]";
SqlCommand mycomm = new SqlCommand(theSQL, cn);
Console.WriteLine(mycomm.CommandText);
try
{
myReader = mycomm.ExecuteReader();
do
{
while (myReader.Read())
{
Console.WriteLine("***** Запись таблиц Друзья и Информация о друзьях: *****");
for (int i = 0; i < myReader.FieldCount; i++)
Console.WriteLine(" {0}= {1}", myReader.GetName(i), myReader.GetValue(i).ToString().Trim());
Console.WriteLine();
}
} while (myReader.NextResult());
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
finally
{
if (myReader != null)
myReader.Close();
if (cn.State == ConnectionState.Open)
cn.Close();
Console.WriteLine("Состояние соединения " + cn.State.ToString());
}
Объекты параметризованных команд. В приведенных примерах каждый SQL-оператор представлен «жестко» закодированными строковыми литералами. С SQL-параметрами можно обращаться, как с объектами, а не с простыми строками текста, если использовать параметризованные запросы. Параметризованные запросы выполняются намного быстрее буквальных SQL-строк, поскольку они анализируются только один раз (а не каждый раз, когда SQL-строка присваивается свойству CommandText).
Объекты команд ADO.NET поддерживают коллекцию дискретных типов параметра. По умолчанию эта коллекция пуста, но в нее можно добавить любое число параметров объекта, которые должны будут отображаться в «заместитель» параметра в SQL–запросе. Чтобы ассоциировать параметр в SQL–запросе с членом коллекции параметров данного объекта команды, к текстовому SQL–параметру добавляют префикс @.
Рассмотрим тип DbParametr, который является базовым классом объектов параметров, специфичных для конкретного поставщика данных (например, SQL Server.NET Data Provider). Этот класс поддерживает ряд свойств, позволяющих указать имя, размер, тип данных параметра.
Таблица. Свойства класса DbParameter
Свойство |
Описание |
DataType |
Определяет тип параметра в терминах .NET |
DbType |
Позволяет получить или задать тип данных, используемый в источнике данных. |
Direction |
Определяет, будет ли этот параметр передаваться в источник данных, возвращаться с источника данных или он сможет использоваться для передачи и в том, и в другом направлении. |
IsNullable |
Позволяет определить, будет ли данный параметр допускать пустые значения (значения типа NULL). |
ParameterName |
Позволяет получить или установить имя (DbParametr) параметра. |
Precision |
Позволяет получить или установить максимальное количество цифр, используемых для значения параметра (определяемое через свойство Value). |
Scale |
Позволяет получить или установить количество десятичных разрядов, используемых для значения параметра. |
Size |
Позволяет получить или установить максимальный размер данных для данного параметра. |
Value |
Позволяет получить или установить значение параметра. |
Создадим параметризованный SQL-запрос, который вставляет новую запись в таблицу «Друзья»:
Console.WriteLine("Создание параметризованного запроса:");
// Сбор информации о новом друге:
Console.WriteLine("Введите код друга!");
int kod_dr = Int32.Parse(Console.ReadLine());
Console.WriteLine("Введите фамилию друга!");
string fam_dr = Console.ReadLine();
Console.WriteLine("Введите отчество друга!");
string ot_dr = Console.ReadLine();
Console.WriteLine("Введите имя друга!");
string imja_dr = Console.ReadLine();
// Создание и формирование параметризованного sql-запроса:
string sqlPar = string.Format("Insert Into Друзья" + "([Код друга], Фамилия, Отчество, Имя) Values" + "(@Код, @Фамилия,@Отчество,@Имя)");
// Имена параметров должны состоять из одного слова! К ним нельзя применять []!!!.
SqlCommand cmdPar = new SqlCommand(sqlPar, cn);
//Наполнение коллекции параметров:
SqlParameter param = new SqlParameter();
param.ParameterName = "@Код";
param.Value = kod_dr;
param.SqlDbType = SqlDbType.Int;
cmdPar.Parameters.Add(param);
param = new SqlParameter();
param.ParameterName = "@Фамилия";
param.Value = fam_dr;
param.SqlDbType = SqlDbType.Char;
param.Size = 20;
cmdPar.Parameters.Add(param);
param = new SqlParameter();
param.ParameterName = "@Отчество";
param.Value = ot_dr;
param.SqlDbType = SqlDbType.Char;
param.Size = 15;
cmdPar.Parameters.Add(param);
param = new SqlParameter();
param.ParameterName = "@Имя";
param.Value = imja_dr;
param.SqlDbType = SqlDbType.Char;
param.Size = 15;
cmdPar.Parameters.Add(param);
Console.WriteLine(cmdPar.CommandText);
try { cmdPar.ExecuteNonQuery(); }
catch (SqlException e) { Console.WriteLine(e.Message); }
Наиболее полезными параметризованные запросы оказываются при запуске хранимых процедур.
Хранимые процедуры. Хранимой процедурой называется одна или несколько SQL-конструкций, которые записаны в базе данных. Задача администрирования базы данных включает в себя в первую очередь распределение уровней доступа к БД. Разрешение выполнения обычных SQL-запросов большому числу пользователей может стать причиной неисправностей из-за неверного запроса или их группы. Чтобы этого избежать, разработчики базы данных могут создать ряд хранимых процедур для работы с данными и полностью запретить доступ для обычных запросов. Такой подход при прочих равных условиях обеспечивает большую стабильность и надежность работы. Это одна из главных причин создания собственных хранимых процедур. Другие причины – быстрое выполнение, разбиение больших задач на малые модули, уменьшение нагрузки на сеть – значительно облегчают процесс разработки и обслуживания архитектуры «клиент – сервер».
Перейдем к созданию своих собственных хранимых процедур. Создадим новый бланк запросов (New Query в контекстном меню базы данных), либо в Server Explorer выбрать в контекстном меню объекта Stored Procedures команду Add New Stored Procedure и введем следующий запрос:
create procedure proc1 as
select [Код туриста], Фамилия, Имя, Отчество from Туристы
Здесь create procedure – оператор, указывающий на создание хранимой процедуры, proc1 – ее название, далее после оператора as следует обычный SQL-запрос. Квадратные скобки необходимы для указания поля таблицы, в названии которого содержится пробел. После выполнения запроса (развернуть ветку «Хранимые процедуры» в среде Management Express и выбрать команду Execute) появится сообщение:
Выполнение команд успешно завершено.
The COMMAND(s) completed successfully.
Вначале появляется шаблон структуры, сгенерированный мастером:
CREATE PROCEDURE dbo.StoredProcedure1
/*
(
@parameter1 int = 5,
@parameter2 datatype OUTPUT
)
*/
AS
/* SET NOCOUNT ON */
RETURN
Для того чтобы приступить к редактированию, достаточно убрать знаки комментариев «/*», «*/». Команда NOCOUNT со значением ON отключает выдачу сообщений о количестве строк таблицы, получающейся в качестве запроса. Необходимость данного оператора заключается в том, что при использовании более чем одного оператора (SELECT, INSERT, UPDATE или DELETE) в начале запроса надо поставить команду SET NOCOUNT ON, а перед последним оператором SELECT – команду SET NOCOUNT OFF.
Например, хранимую процедуру proc_po1 можно переписать следующим образом:
CREATE PROCEDURE dbo.proc_vs1
(
@TouristID int,
@LastName nvarchar(60) OUTPUT
)
AS
SET NOCOUNT ON
SELECT @LastName = Фамилия
FROM Туристы
WHERE ([Код туриста] = @TouristID)
RETURN
После завершения редактирования SQL-конструкция будет обведена синей рамкой. Щелкнув правой кнопкой в этой области и выбрав пункт меню «Разработать блок SQL» («Design SQL Block»), можно перейти к построителю запросов (Query Builder). Для выполнения процедуры необходимо в выпадающем меню процедуры выбрать пункт Execute.
Чтобы выполнить хранимую процедуру в программном коде приложения, следует, как всегда, сначала создать новый объект соединения, сформировать строку соединения и открыть сеанс. При создании объекта команды свойству CommandText нужно присвоить имя хранимой процедуры, а не SQL-запроса. Также нужно установить для свойства CommandType значение CommandType.StoredProcedure.
//SqlCommand com = new SqlCommand("proc1", cn);
//com.CommandType = CommandType.StoredProcedure;
//com.ExecuteNonQuery();
На практике часто возникает потребность получить информацию из БД по некоторому заданному значению «входных» данных (параметру) запроса. Такие запросы называются параметризированными, а соответствующие процедуры создаются с параметрами. Например, для получения записи в таблице «Туристы» по заданной фамилии создадим следующую процедуру:
create proc proc_p1
@Фамилия nvarchar(50)
as
select *
from Туристы
where
Фамилия=@Фамилия
После знака @ указывается название параметра и его тип. Таким образом, для параметра с именем Фамилия был выбран тип nvarchar c количеством символов 50, поскольку в самой таблице для поля «Фамилия» установлен этот тип.
Попытка запустить процедуру командой exec proc_p1 приводит к появлению сообщения об отсутствующем параметре. Процедуру необходимо запускать следующим образом:
exec proc_p1 'Андреева'
