Практическая работа по теме 1. &quot

advertisement
Практическая работа по теме 1. "Новейшие направления
в области создания технологий программирования"
Использование инструментов Visual Studio.NET для создания баз данных и написания
хранимых процедур. Основные объекты провайдера данных: объект Connection, объект
Command. Применение объекта Command с параметрами и хранимыми процедурами.
Метод выполнения команд ExecuteNonQuery. Метод ExecuteScalar. Метод ExecuteReader
и объект DataReader. Транзакции к базе данных - объект Transaction.
Оглавление
Задание 1. Использование инструментов Visual Studio для
создания базы данных
Задание 2. Основные объекты провайдера данных: объект
Connection
Задание 3. Основные объекты провайдера данных: объект
Command
Задание 4. Применение объекта Command с параметрами и
хранимыми процедурами
Задание 5. Выполнение команд: метод ExecuteNonQuery
Задание 6. Выполнение команд: метод ExecuteScalar Цель
Задание 7. Выполнение команд: метод ExecuteReader и объект
DataReader
Задание 8. Другие объекты провайдеров данных: объект
Transaction
Задание 1. Использование инструментов Visual Studio для
создания базы данных
Цель
Научиться использовать инструменты Visual Studio.NET для создания базы данных.
Решение
Использовать компонент Visual Studio.NET Server Explorer для создания новой базы
данных, определения структуры таблиц, индексов и первичных ключей таблиц, создания
схемы базы данных и установления отношений между таблицами.
Обсуждение
Существует несколько способов создания баз данных в SQL Server. С помощью набора
инструментов SQL Enterprise Manager базы данных можно создавать графически или
программно (с помощью команд на языке SQL). Кроме этого инструмента, существует
множество других внешних инструментов для создания баз данных, например, Microsoft
Visio.
Среда Visual Studio.NET также содержит очень удобный
инструмент для работы с базами данных MS SQL Server.
Инструментарий входит в состав компонента Server
Explorer, который предназначен для централизованного
управления всеми видами серверного программного
обеспечения.
Рассмотрим создание базы данных, предназначенной для
хранения следующей информации о каждом сотруднике
компании:

Название отдела, в котором работает
служащий;
 Размер полученной сотрудником заработной
платы;
 Размер иных доходов сотрудника;

Перечень курсов, которые посещал служащий компании в целях
повышения квалификации.
Структура базы даны, включая отношения между таблицами, приведена на рис. 1.1.
Рис. 1.1. Структура базы данных
Чтобы создать новую базу данных выполните следующие действия:
1. Запустите интегрированную среду разработки Visual Studio.NET.
2. В левой части окна Visual Studio откройте окно Server Explorer, выбрав команду меню
View - Server Explorer.
3. В этом окне раскройте узел Servers, найдите ваш компьютер, а затем раскройте узел
SQL SERVER и найдите в нем экземпляр SQL Server, который установлен на вашем
компьютере, как показано на рисунке.
4. Для создания новой базы данных щелкните правой кнопкой мыши на имени экземпляра
SQL Server, который установлен на вашем компьютере. В контекстном меню выберите
команду New Database (создать новую базу данных).
5. На экране появится диалоговое окно Create Database (создать базу данных). Введите
имя новой базы данных и щелкните OK.
6. После этого в окне Server Explorer появится новая база данных.
В нашем случае HumanResources.
При раскрытии узла этой базы данных будут отображены следующие категории объектов
базы данных:





Database Diagrams (Диаграммы базы данных);
Tables (Таблицы);
Views (Представления);
Stored Procedures (Хранимые процедуры);
Functions
(Функции).
7. Для создания таблиц нашей базы данных щелкните правой кнопкой
мыши на узле Tables базы данных HumanResources, а затем из
контекстного меню выберите команду New Tables (Создать таблицы). В
соответствии с моделью на рис. 1.1. создайте таблицы средствами Visual
Studio.
На рис. 1.2 представлены поля таблицы Departmens. После ввода названия поля, следует
указать его тип и размер. Если значения, вводимые в данное поле, будут уникальными, то
необходимо указать, что поле является ключевым. Для этого щелкните на поле правой
кнопкой мыши и выберите команду меню Diagram-Set Primary Key.
Рис. 1.2. Создание структуры таблицы с помощью Visual Studio.NET
Далее нужно указать, что ключевое поле (если это первичный ключ) используется в SQL
Server в целях автоматической генерации идентификационных значений.
Щелкните правой кнопкой мыши на окне с определением таблицы (можно в строку с
первичным ключом таблицы) и выберите в контекстном меню Index/Keys
(индексы/ключи)/. После этого на экране появится диалоговое окно Property Pages,
имеющее вкладку Index/Keys. В списке Table Identify Column выберите ключевое поле
вашей таблицы.
После установления первичных ключей таблицу можно сохранить: File-Save Table1. В
диалоговом окне Choose Name введите имя и нажмите OK. Обратите внимание, что ваша
таблица появилась в окне компонента Server Explorer.
Проделайте аналогичные процедуры создания для всех таблиц нашей модели.
8. Теперь, когда вы создали таблицы, осталось определить индексы (index).
Индексы присваиваются полю, чтобы облегчить выборку данных на основе информации,
хранимой в поле, например, в случае установления индекса для поля фамилия, поиск
клиента по этому полю будет выполняться быстрее. Следует иметь в виду, что индексы
увеличивают размер базы данных, то есть объем хранимой информации и объем
занимаемой памяти, что приводит к снижению скорости работы компьютера.
Злоупотреблять количеством индексов не следует.
Для того чтобы добавить индекс к одному из полей таблицы следует выполнить
перечисленные ниже действия:
 Щелкните правой кнопкой мыши на окне с определением таблицы,
например, Employees и выберите в контекстном меню команду
Index/Keys.

После этого на экране появится страница свойств со списком
существующих индексов, в котором уже присутствует индекс первичного
ключа EmployeeId. Щелкните на кнопке New (Создать) для создания
нового индекса для поля, например, FirstName.
 В списке полей выберите поле FirstName, как показано на рис.1.3, а
затем щелкните на кнопке Close.
 Повторите действия из пп. 1-3, чтобы создать все остальные индексы.
В нижней части диалогового окна Property Pages находится параметр Create UNIQUE
(Создать уникальный индекс). Не устанавливайте флажок для этого параметра, потому что
в таком случае в таблицу можно будет вводить только разные имена сотрудников.
Уникальные индексы следует создавать только для того, чтобы гарантировать
уникальность значений данного поля.
9. Для сохранения внесенных изменений в базу данных выберите команду меню File Save Employees. После успешного сохранения внесенных изменений закройте окно
создания базы данных visual Studio.NET.
Рис. 1.3. Диалоговое окно Property Pages после определения индекса для поля
FirstName
10. Создание схемы базы данных. Схема базы данных (database diagram) - это визуальное
представление таблиц в базе данных. Для создания таблиц и отношений между ними
можно использовать инструменты SQL Server, но можно использовать средства среды
Visual Studio.NET.
Разверните узел нашей базы данных HumanResources в окне Server Explorer, щелкнув
правой кнопкой мыши на узле Database Diagrams, и выберите в контекстном меню
команду New Diagram (создать схему).
В диалоговом окне Add Table (Добавить таблицу) будет приведен список таблиц вашей
базы данных. Выберите все и/или нужные таблицы и щелкните на кнопке Add (Добавить),
а затем на кнопке Close.
11. Для установления связей между таблицами следует установить связь (отношение)
между ними следующим образом: щелкнуть на ключевом поле таблицы, например,
Employees и перетащить его к полю DepartmentHeadId в таблице Departments.
На экране появится диалоговое окно Create relationship (создать отношения), в котором
можно указать свойства отношения между двумя таблицами.
В результате будет создана новая схема базы данных (рис. 1.4).
Рис. 1.4. Схема базы данных с установленными отношениями между таблицами
12. Для сохранения созданной схемы базы данных Database Diagram1 выберите команду
File - Save DatabaseDiagram1. В диалоговом окне Save New Database Diagram (сохраните
имя новой схемы базы данных) введите имя, например, Relationships для новой схемы
базы данных.
После создания базы данных можно приступить к написанию программного кода для
нашего приложения. Сразу необходимо заметить, что приложение, которое мы с вами
сейчас начнем разрабатывать, не будет полнофункциональным приложением. Целью
изучаемого примера является всего лишь иллюстрация изученных ранее объектов для
построения приложения по обработке информации. В приложении создадим
единственную форму для работы с записями таблицы Employees. Форма под названием
EmployeesDetails будет предназначена для добавления или удаления служащих компании,
редактирования личной информации о служащих, включая принадлежность к тому или
иному отделу, и текущий уровень заработной платы.
Самостоятельно
1. Средствами Visual Studio.NET создайте базу данных Dogovor по
модели,
представленной
на
рис.
1.5.
2. Так как база данных Dogovor является основой для выполнения всех
последующих заданий текущего практикума, внесите в нее данные
(непосредственно в таблицы).
Рис. 1.5. База данных Dogovor
Задание 2. Основные объекты провайдера данных: объект
Connection
Цель
Познакомиться с объектом Connection, обеспечивающим соединение с заданным
источником данных.
Решение
Необходимо рассмотреть объекты OleDbConnection, SqlConnection и OdbcConnection,
реализующие одинаковые интерфейсы, но имеющие различную реализацию.
Обсуждение
Объект Connection служит для установления соединения с заданным источником данных
и с указанным в строке подключения учетным именем и паролем. Соединение можно
настроить, редактируя нужным образом значения параметров строки подключения.
Объекты OleDbConnection, SqlConnection и OdbcConnection реализуют одинаковые
интерфейсы, но все же имеют разные реализации, то есть имеют разный формат строки
подключения. В объектах OleDbConnection и OdbcConnection используется стандартный
формат строки подключения OLEDB или ODBC с незначительными исключениями.
Пример формирования строки подключения для провайдера OleDbConnection рассмотрен
ниже.
Объект OleDbConnection представляет уникальное подключение к источнику данных. Для
клиент-серверных систем баз данных этот объект является эквивалентом сетевого
подключения к серверу. В зависимости от функциональных возможностей,
поддерживаемых собственным поставщиком OLE DB, некоторые методы или свойства
объекта OleDbConnection могут оказаться недоступными.
При создании экземпляра OleDbConnection для всех свойств задаются начальные
значения. Если объект OleDbConnection выходит за границы области действия, он не
закрывается. Поэтому необходимо явно закрыть подключение, вызвав методы объекта
OleDbConnection Close или Dispose.
Dim
myConnection
As
New
OleDbConnection(myConnectionString)
myConnectionString
=
"Provider=SQLOLEDB;Data
Source=localhost;Initial Catalog=Northwind;Integrated
Security=SSPI;"
В приведенной ниже таблице представлены параметры объекта ConnectionString.
Имя
Initial
Database
Описание
Catalog|
Имя базы данных
Если имеет значение false, в подключении
определяются
идентификатор
и
пароль
пользователя. Если имеет значение true, для
Integrated
Security| аутентификации используются текущие учетные
Trusted_Connection
данные
Windows.
По
умолчанию
false.
Распознаваемые значения: true, false, yes, no и
sspi
(настоятельно
рекомендуется),
что
эквивалентно true.
Password| Pwd
Пароль для подключения к SQL Server (не
рекомендуется).
Для
поддержки
наивысшего
уровня безопасности настоятельно рекомендуется
использовать вместо этого зарезервированные
слова
"Integrated
Security"
или
"Trusted_Connection").
Persist Security Info
Если задано значение false или no (настоятельно
рекомендуется)
сведения
о
безопасности
(например, пароль) не возвращаются как часть
подключения, если оно открыто или когда-либо
находилось в открытом состоянии. По умолчанию
false.
Идентификатор
пользователя
Имя для подключения к SQL Server (не
рекомендуется).
Для
поддержки
наивысшего
уровня безопасности рекомендуется использовать
зарезервированные слова "Integrated Security" или
"Trusted_Connection".
Workstation ID
Имя рабочей станции, подключающейся к SQL
Server
(по
умолчаниюимя
локального
компьютера).
При задании зарезервированных слов, требующих логических значений, можно
использовать yes вместо true и no вместо false. Целочисленные значения предоставляются
в виде строк.
В объекте SqlConnection используется несколько иной формат строки подключения,
который имеет отношение только к SQL Server версии 7.0 и выше.
Синтаксис ConnectionString аналогичен, но не идентичен строке подключения OLE DB. В
отличие от OLE DB, возвращаемая строка подключения совпадает с задаваемой
пользователем ConnectionString, за исключением сведений о безопасности в случае, если
Persist Security Info имеет значение false (значение по умолчанию). Провайдер данных
.NET Framework для SQL Server не сохраняет и не возвращает пароль в строке
подключения, если значение Persist Security Info отлично от true.
Для подключения к базе данных можно использовать свойство ConnectionString. В
следующем примере показана типичная строка подключения.
Public
Sub
CreateSqlConnection()
Dim
myConnection
As
New
SqlConnection()
myConnection.ConnectionString
=
"Persist
Security
Info=False;Integrated
Security=SSPI;database=northwind;server=mySQLServer;Connect
Timeout=30"
myConnection.Open()
End Sub 'CreateSqlConnection
Самостоятельно
1. Создайте проект, в форме которого поместите текстовое окно и
командную
кнопку
(рис.
1.6).
2. Для командной кнопки введите программный код, реализующий:
 Создание экземпляра объекта Connection;
 Создание строки подключения;
 Отображение состояния подключения;
 Открытие подключения;
 Отображений состояния подключения.
Пример кода, реализующего подключение к базе данных с помощью провайдера SqlClient,
представлен ниже.
3. Самостоятельно напишите подключение к базам данных с использование других
провайдеров: OleDb и ODBC.
Private
Sub
Button1_Click(ByVal
sender
As
System.Object, ByVal e As System.EventArgs) Handles
Button1.Click
Dim
cnn
As
New
SqlConnection
cnn.ConnectionString = "Persist Security Info=False;
Integrated
Security=SSPI;
database=Dogovor;
server=abrzh"
TextBox1.Clear()
If (cnn.State = System.Data.ConnectionState.Open)
Then
TextBox1.Text = TextBox1.Text & "Connection is Open"
Else
TextBox1.Text = TextBox1.Text & "Connection is
Closed"
End
If
TextBox1.Text = TextBox1.Text & ControlChars.CrLf
TextBox1.Text = TextBox1.Text & "Opening SQL
connection.." & ControlChars.CrLf & ControlChars.CrLf
cnn.Open()
If (cnn.State = System.Data.ConnectionState.Open)
Then
TextBox1.Text = TextBox1.Text & "Connection is Open"
Else
TextBox1.Text = TextBox1.Text & "Connection is
Closed"
End
If
cnn.Close()
End Sub
4. После запуска полученного приложения и щелчка по кнопке в текстовом поле появится
строки о закрытии подключения, о состоянии подключения и повторном открытии
подключения как показано на рис. 1.6.
Рис. 1.6. Запуск приложения с подключением к базе данных
Задание 3. Основные объекты провайдера данных: объект
Command
Цель
Познакомиться с объектом Command, обеспечивающим выполнение команд по
отношению к источнику данных, а также получение возвращенных данных или
результатов выполнения команд.
Решение
Необходимо рассмотреть объекты OleDbCommand, SqlCommand и OdbcCommand,
реализующие одинаковые интерфейсы, но имеющие различную реализацию.
Обсуждение
Объект Command служит для выполнения команд по отношению к источнику данных.
Объект имеет следующие свойства: CommandText и CommandType для определения
текста и типа фактической команды; Connection для указания подключения,
используемого для выполнения команды; CommandTimeout для указания времени
ожидания, по истечению которого команда отменяется и выдается сообщение об ошибке;
Parameters для коллекции параметров команды; Transaction для указания транзакции, в
которой используется данная команда.
Все три версии объекта Command имеют идентичные свойства и методы, за исключением
того, что объект SqlCommand имеет дополнительный метод, которого нет у двух других
вариантов этого объекта, а именно ExecuteXMLReader. Он использует преимущества SQL
Server для автоматического возвращения данных в формате XML (если в запрос SQL
добавлено предложение FOR XML).
Еще одно отличие между версиями объекта Command для разных провайдеров данных
заключается в использовании свойства CommandType. Все они поддерживают значения
Text и StoredProcedure, а объекты OleDbCommand поддерживают еще одно, третье
возможное значение - TableDirect. Это позволяет эффективно загружать все содержимое
таблицы за счет установки значения TableDirect для свойства CommandType и имени
таблицы для свойства CommandText.
Самостоятельно
1. Продолжим работу с проектом задания 2. Добавим в форму еще одну
командную кнопку, которая будет выполнять подключение к базе
данных
и
инициировать
объект
Command.
2. В обработчике события кнопки запишем следующий программный код.
Private
Sub
Button2_Click(ByVal
sender
As
System.Object, ByVal e As System.EventArgs) Handles
Button2.Click
Dim
cnn
As
New
SqlConnection
cnn.ConnectionString
=
"Persist
Security
Info=False;Integrated
Security=SSPI;database=Dogovor;server=abrzh"
Dim
cmd
As
New
SqlCommand
TextBox1.Clear()
cnn.Open()
cmd.Connection
=
cnn
cmd.CommandType
=
CommandType.Text
cmd.CommandText = "Select dogovor_Num, tovar
from
Dogovor"
TextBox1.Text
=
"Command
Strind:"
&
ControlChars.CrLf
TextBox1.Text = TextBox1.Text & ControlChars.Tab &
cmd.CommandText
&
ControlChars.CrLf
cnn.Close()
End Sub
3. Попробуйте запустить проект, нажмите кнопку Command. Измените содержимое строки
CommandText и убедитесь, что вы записали ее верно (рис. 1.7).
Рис. 1.7. Открытие подключения к базе данных и подготовка объекта Command
Задание 4. Применение объекта Command с параметрами и
хранимыми процедурами
Цель
Изучить способы использования объекта Command для выполнения запросов или
хранимых процедур к источнику данных с передачей входных и выходных параметров.
Решение
Использовать свойство Parameters объекта Command.
Обсуждение
Теперь рассмотрим применение объекта Command с параметрами и хранимыми
процедурами.
При создании запросов или команд часто требуется передавать значения параметров
действия (обновление, вставка или удаление данных) или хранимой процедуры. Для
решения этой проблемы в объекте Command предусмотрено свойство Parameters, которое
является объектом ParameterCollection и содержит коллекцию объектов-параметров
Parameter.
Способы программирования объекта SqlParameterCollection и использование объектов
ODBCParameterCollection, OleParameterCollection имеют существенные отличия. Объекты
OdbcParameterCollection и OleDbParameterCollection основаны на позиционных
параметрах, а объект SqlParameterCollection - на именованных параметрах. Эти различия в
значительной степени влияют на способ определения запросов и параметров.
Создадим простой запрос с параметрами для извлечения из базы данных dogovor
поставщиков заказа с заданным номером. С одной стороны, при использовании
провайдера данных OLEDB или ODBC запрос будет иметь следующий вид:
Select
postavshik
dogovor_Num=?
FROM
dogovor
WHERE
Здесь вопросительный знак заменяет один параметр, а для нескольких параметров можно
использовать несколько вопросительных знаков. Порядок расположения параметров
важен. С другой стороны, при использовании провайдера данных SqlClient запрос будет
выглядеть следующим образом:
Select
postavshik
FROM
dogovor_Num=@MyParam
dogovor
WHERE
Здесь заменителем параметра является его имя, а дополнительные параметры также
обозначаются их именами, поэтому порядок расположения параметров не важен.
Объект Parameter можно создавать явно, используя для этого конструктор New Parameter,
или передавая нужные аргументы методу Add объекту ParameterCollection (то есть
свойству parameters объекта Command). Помните, что оба метода (конструктор Parameter и
метод Add) имеют перегруженные версии, то есть, вы можете пользоваться любой
версией из списка предлагаемых .NET.
Внесите изменения в код кнопки Command, как показано ниже. После запуска программы
и щелчка по кнопке Command в текстовом поле появится текст запроса, а также имя и
значение параметра (рис. 1.8).
Private
Sub
Button2_Click(ByVal
sender
As
System.Object, ByVal e As System.EventArgs) Handles
Button2.Click
Dim cnn As New SqlConnection("Persist Security
Info=False;Integrated
Security=SSPI;database=Dogovor;server=abrzh")
Dim
cmd
As
New
SqlCommand
Dim
prm
As
New
SqlParameter
TextBox1.Clear()
cnn.Open()
cmd.Connection
=
cnn
cmd.CommandType
=
CommandType.Text
cmd.CommandText = "Select postavshik from Dogovor
where
tovar=@MyParam"
cmd.Parameters.Add(New SqlParameter("@MyParam",
SqlDbType.VarChar,
50))
cmd.Parameters("@MyParam").Value
=
"товар1"
TextBox1.Text
=
"Command
Strind:"
&
ControlChars.CrLf
TextBox1.Text = TextBox1.Text & ControlChars.Tab &
cmd.CommandText
&
ControlChars.CrLf
TextBox1.Text
=
TextBox1.Text
&
"Command
parameters:"
&
ControlChars.CrLf
For
Each
prm
In
cmd.Parameters
TextBox1.Text = TextBox1.Text & ControlChars.Tab &
prm.ParameterName & " = " & prm.Value &
ControlChars.CrLf
Next
cnn.Close()
End Sub
Рис. 1.8. Применение объекта Command с параметрами
Аналогично вызываются хранимые процедуры, за исключением того, что вместо свойства
CommandType.Text используется свойство CommandType.StoredProcedure, а имя хранимой
процедуры присваивается свойству CommandText.
Создание хранимой процедуры возможно с помощью программы SQL SERVER Enterprise
Manager или программы SQL Query Analyzer. Но Visual Studio.NET также располагает
средствами разработки таких процедур.
4. Для создания хранимой процедуры средствами Visual Studio.NET выберите на вкладке
Server Explorer команду Stored Procedure - New Stored Procedure (рис. 1.9).
Рис. 1.9. Шаблон для создания хранимой процедуры
5. В появившемся шаблоне следует описать входные и выходные параметры (если
требуются), а для создания текста самой процедуры следует перейти по правой кнопке с
помощью команды Insert SQL в дизайнер SQL и построить текст процедуры в
графическом режиме (рис. 1.10).
Рис. 1.10. Графический дизайнер SQL для построения хранимых процедур
6. Для выхода из дизайнера необходимо сохранить процедуру (File - Save Stored Procedure)
и закрыть окно дизайнера, тогда вы снова окажетесь в окне кода хранимой процедуры
(рис. 1.11).
Рис. 1.11. Код хранимой процедуры
7. Для нашего примера создадим хранимую процедуру StoredProcedure4, выполняющую
следующие команды:
ALTER
AS
SELECT
FROM
GROUP
HAVING
RETURN
Код вызова
следующий
PROCEDURE
dbo.StoredProcedure4
BY
(COUNT(dogovor_Num)
хранимой
процедуры
postavshik
Dogovor
postavshik
>
1)
может
Dim cnn As New SqlConnection("Persist
Info=False;Integrated
иметь
вид:
Security
Security=SSPI;database=Dogovor;server=abrzh")
cnn.Open()
Dim
cmd
As
New
SqlCommand
cmd.Connection
=
cnn
cmd.CommandType = CommandType.StoredProcedure
cmd.CommandText
=
"StoredProcedure4"
cmd.CommandType = CommandType.StoredProcedure
В случае вызова хранимой процедуры с параметрами необходимо описать создание
параметра, добавление его в коллекцию Parameters и указать его значение. Рассмотрим,
как изменится код самой хранимой процедуры и код вызова этой процедуры в проекте.
8. Текст хранимой процедуры для поиска поставщиков, имеющих некоторое (задаваемое
пользователем) количество договоров поставки:
ALTER
@par
AS
SELECT
FROM
GROUP
HAVING
RETURN
PROCEDURE
BY
(COUNT(dogovor_Num)
StoredProcedure4
int
postavshik
Dogovor
postavshik
>
@par)
9. При наличии входного параметра, код вызова хранимой процедуры несколько
изменится:
Dim cnn As New SqlConnection("Persist Security
Info=False;Integrated
Security=SSPI;database=Dogovor;server=abrzh")
cnn.Open()
Dim
cmd
As
New
SqlCommand
Dim
reader
As
SqlDataReader
cmd.Connection
=
cnn
cmd.CommandType = CommandType.StoredProcedure
cmd.CommandText
=
"StoredProcedure4"
cmd.CommandType = CommandType.StoredProcedure
cmd.Parameters.Add(New
SqlParameter("@par",
SqlDbType.Int,
4))
cmd.Parameters("@par").Direction
=
ParameterDirection.Input
cmd.Parameters("@par").Value = 1
Самостоятельно
1.
Напишите
хранимую
процедуру
с
параметрами.
2. Опишите вызов этой процедуры с помощью свойств объекта Command.
Для ввода значений входных параметров используйте элементы
интерфейса (Textbox или InputBox).
Задание 5. Выполнение команд: метод ExecuteNonQuery
Цель
Выполнить команды по отношению к источнику данных с помощью объекта Command и
его методов.
Решение
Использовать один из методов объекта Command: метод ExecuteNonQuery.
Обсуждение
Теперь пришло время рассмотреть, каким образом команды выполняются. Для этого у
объекта Command имеются методы:
Метод ExecuteNonQuery - выполняет команду SQL и не возвращает значение.
Метод ExecuteScalar - выполняет команду SQL и возвращает первое поле первой записи.
Метод ExecuteReader - выполняет команду SQL и возвращает набор записей с помощью
объекта DataReader.
Метод ExecuteXMLReader (только для SqlCommand) - выполняет команду SQL и
возвращает набор записей в формате XML с помощью объекта XMLReader.
Метод ExecuteNonQuery возвращает только целочисленное значение, сообщающее об
успешном или неудачном исходе выполнения команды.
При удачном выполнении DDL-команд определения данных для изменения структуры баз
данных возвращается значение -1, а при удачном выполнении DML-команд управления
данными для их обновления, вставки или удаления возвращается количество строк,
задействованных в команде. При неудачном выполнении обоих типов возвращается
значение 0.
1. Продолжая работу с проектом, попробуем использовать объекты пространства имен
SQLClient и базу данных Dogovor. Наша задача - изменить стоимость всех товаров на
10%. Введите для новой кнопки формы следующий код, выполняющий обновление
таблицы базы данных с помощью команды UPDATE с параметром.
Private
Sub
Button3_Click(ByVal
sender
As
System.Object, ByVal e As System.EventArgs) Handles
Button3.Click
Dim cmd As New SqlCommand, cnn As New
SqlConnection
cnn.ConnectionString
=
"Persist
Security
Info=False;Integrated
Security=SSPI;database=Dogovor;server=abrzh"
TextBox1.Clear()
cmd.Connection
=
cnn
cmd.CommandText
=
"UPDATE
Tovar
SET
cena=cena*@par"
cmd.Parameters.Add(New
SqlParameter("@par",
SqlDbType.Float,
4))
cmd.Parameters("@par").Direction
=
ParameterDirection.Input
cmd.Parameters("@par").Value
=
1.1
cnn.Open()
Dim
i
As
Integer
i
=
cmd.ExecuteNonQuery()
If
i
<>
0
Then
TextBox1.Text
=
"цена
товара
увеличена"
Else
TextBox1.Text
=
"не
получилось"
End
If
cnn.Close()
End Sub
2. Теперь таблицу со стоимостью товаров в базе данных Dogovor можно обновить,
запустив приложение. Значение параметра можно вводить из текстового окна .
cmd.Parameters("@par").Value = val(Textbox1.Text )
3. После запуска приложения и щелчка по кнопке Button3 вы должны увидеть в текстовом
окне сообщение об успешном или неудачном исходе, а сами значения стоимости товаров
можно посмотреть с помощью Server Explorer непосредственно в таблице Tovar (рис.
1.12).
Если таблица Tovar была открыта, то изменения в столбце Tovar сразу не будут
отображены. Необходимо или закрыть и открыть таблицу Tovar, или вызвать по правой
кнопке мыши команду Refresh (Обновить) для этой таблицы.
Рис. 1.12. Обновление таблицы базы данных с помощью объектов SQLClient
Самостоятельно
4. Выполните обновление стоимости товаров с помощью хранимой
процедуры, написанной самостоятельно. Использование хранимых
процедур позволяет добиться более высокой производительности
обработки
баз
данных
и
централизованно
хранить
код.
5. При создании хранимой процедуры обязательно укажите тип SQL
команды: в нашем случае это команда на изменение записей. Тип
укажите в раскрывающемся списке Change Type как показано на рис.
1.13.
Примечание
Из практического опыта организации ввода входных значений параметров хранимой
процедуры: при вводе значений параметров из интерфейсных элементов, например,
TextBox, необходимо очищать элемент или вводить значения параметров через окно
стандартного диалога InputBox.
Рис. 1.13. Указание типа команды SQL
Задание 6. Выполнение команд: метод ExecuteScalar
Цель
Выполнить команды по отношению к источнику данных с помощью объекта Command и
его методов.
Решение
Использовать один из методов объекта Command: метод ExecuteScalar.
Обсуждение
Метод ExecuteScalar - выполняет команду SQL и возвращает первое поле первой записи. В
каких случаях используется этот метод? Иногда требуется выполнить команду, которая
возвращает скалярное значение, то есть только одно значение. Типичными примерами
являются команды SQL для вычисления суммы всех значений или общего количества
записей (Sum или Count). Другими примерами являются справочные таблицы для
подстановки одного значения или команды, возвращающие логические значения.
Метод ExecuteScalar выполняет заданную команду и возвращает значение только первого
поля первой записи, остальные записи игнорирует.
1. Напишем для нашей базы данных Dogovor хранимую процедуру для подсчета
количества договоров на поставку товара определенного типа, например, 'Товар1'.
ALTER
AS
SELECT
PROCEDURE
COUNT(*)
dbo.StoredProcedure3
AS
Expr1
FROM
WHERE
RETURN
(tovar
=
Dogovor
'Товар1')
2. Для вызова хранимой процедуры с помощью провайдера данных SQLClient выполните
следующие действия:
 Создайте дополнительную кнопку и назовите ее ExeciteScalar.

Создайте код обработчика события щелчка по этой кнопке. Код
приведен ниже.
 Запустите приложение и просмотрите результат.

Измените содержимое таблицы Dogovor и снова запустите
приложение.
На рис. 1.14 представлен результат поиска записей в таблице базы данных и содержание
самой таблицы.
Private
Sub
Button5_Click(ByVal
sender
As
System.Object, ByVal e As System.EventArgs) Handles
Button5.Click
Dim cnn As New SqlConnection("Persist Security
Info=False;Integrated
Security=SSPI;database=Dogovor;server=abrzh")
Dim
cmd
As
New
SqlCommand
cmd.Connection
=
cnn
cmd.CommandType = CommandType.StoredProcedure
cmd.CommandText
=
"StoredProcedure3"
cnn.Open()
Dim
result
As
Integer
result
=
cmd.ExecuteScalar
TextBox1.Text
=
cnn.State.ToString
TextBox1.Text = TextBox1.Text & ControlChars.CrLf &
"Количество
договоров
"
&
result.ToString
cnn.Close()
TextBox1.Text = TextBox1.Text & cnn.State &
ControlChars.CrLf
End Sub
Рис. 1.14. Результат поиска записей методом ExecuteScalar
Самостоятельно
3. Напишите свой код извлечения скалярного значения из хранимой процедуры с
помощью провайдера OleDb.
Задание 7. Выполнение команд: метод ExecuteReader и объект
DataReader
Цель
Выполнить команды по отношению к источнику данных с помощью объекта Command и
его методов.
Решение
Использовать один из методов объекта Command: метод ExecuteReader.
Обсуждение
Метод ExecuteReader применяется для возвращения набора записей. В большинстве
приложений для работы с базами данных именно этот метод используется чаще всего.
Работа метода основана на объекте DataReader, с помощью которого записи
обрабатываются последовательно одна за другой.
Объект DataReader предназначен для чтения в прямом направлении небуферизуемого
потока записей, полученных от метода ExecuteReader объекта Command.
Объект DataReader предлагает наиболее быстрый способ доступа к источнику данных, но
не предусматривает возможности прокрутки и обновления данных. Для перехода к
следующей записи объекта DataReader нужно вызвать его метод Read.
Доступ к полям каждой записи данных объекта DataReader можно выполнять
следующими способами:
1. С помощью строго типизированных методов доступа. Эти методы извлекают значение
поля по номеру поля; нумерация полей начинается с нуля, например:
X=MyReader.GetInt(1)
или
X=MyReader.GetString(2).
2. С помощью коллекции Fields, в которой используются имена полей, что значительно
упрощают чтение кода программы.
X=MyReader("MyField").
Следует иметь в виду, что первый способ извлечения данных повышает
производительность программы, так как используется номер поля, что исключает
преобразование имени поля в его номер. Рассмотрим применение метода на практике. Для
демонстрации способов использования метода ExecuteReader совместно с объектом
DataReader добавим в проект еще одну кнопку и введем следующий код:
Private
Sub
Button4_Click(ByVal
sender
As
System.Object, ByVal e As System.EventArgs) Handles
Button4.Click
Dim
cnn
As
New
OleDbConnection("Provider=SQLOLEDB.1;Integrated
Security=SSPI;Persist
Security
Info=False;Initial
Catalog=Dogovor;Data
Source=ABRZH;Workstation
ID=ABRZH")
Dim
cmd
As
New
OleDbCommand
Dim
reader
As
OleDbDataReader
TextBox1.Clear()
cmd.Connection
=
cnn
cmd.CommandType
=
CommandType.TableDirect
cmd.CommandText
=
"Dogovor"
cnn.Open()
reader
=
cmd.ExecuteReader
While
reader.Read
TextBox1.Text = TextBox1.Text & reader("Postavshik")
&
ControlChars.Tab
&
reader("tovar")
&
ControlChars.CrLf
End
While
reader.Close()
cnn.Close()
End Sub
На рис. 1.15 представлен результат извлечения данных с помощью объекта DataReader и
метода ExecuteReader. Обратите внимание, на использование значение TableDirect для
свойства CommandType объекта Command. Значение TableDirect поддерживается только
для провайдера OLE DB.
Примечание
Каждое обращение к данным с помощью объекта DataReader должно выполняться
принудительно - вызовом метода Read().
3. По окончании использования объекта DataReader следует вызывать метод Close(). Дело
в том, что выходные данные или возвращаемые значения для объекта Command
недоступны до тех пор, пока объект DataReader открыт. Объект остается открытым до тех
пор, пока открыто само подключение или объект DataReader.
Рис. 1.15. Извлечение значений полей с помощью метода ExecuteReader
Самостоятельно
4. Примените объект DataReader и метод ExecuteReader для провайдера данных SQLClient.
Задание 8. Другие объекты провайдеров данных: объект
Transaction
Цель
Научиться выполнять транзакции к базе данных.
Решение
Провайдеры данных ADO.NET содержат объект Transaction, который имеет
фундаментальные методы обработки транзакций.
Обсуждение
Транзакции используются для гарантированного успешного завершения сразу нескольких
операций по принципу "все или ничего". Это значит, что-либо все операции транзакции
успешно выполняются, либо они вообще не выполняются.
Классическим примером транзакции является банковская операция перечисления
денежных средств. Эта операция состоит из двух этапов: удержание денежной суммы с
одного счета и зачисление ее на другой счет. При этом желательно избегать ситуаций,
когда успешно выполняется только первый этап транзакции.
Провайдеры данных ADO.NET содержат объект Transaction, который имеет
фундаментальные методы обработки транзакций. Метод Commit фиксирует текущую
транзакцию, а метод Rollback - откатывает (отменяет) текущую транзакцию.
Выполнение транзакций и создание объекта Transaction осуществляется с помощью
вызова метода BeginTransaction по отношению к открытому объекту Connection.
Рассмотрим способ использования объекта Transaction на примере архивирования старых
договоров по годам.
После относительно длительного использования системы управления базами данных
некоторые данные рекомендуется архивировать. В каждой рабочей системе операцию
архивирования следует включить в состав обязательных и регулярно выполняемых
операций резервного копирования.
Архивируемые данные - это данные, которые нужны не для постоянного использования (в
оперативном режиме), а только изредка. Удаление этих данных из основных оперативных
таблиц базы данных может повысить производительность операций доступа к этим
таблицам, так как при этом приходится обрабатывать и фильтровать меньше записей.
Однако архивная таблица часто хранится в идентичном формате таблицы и доступ к ней в
случае необходимости можно организовать аналогичным образом. Создадим простую
форму для архивирования данных из таблицы Dogovor. Форма должна позволять
выбирать и архивировать договоры по годам:
 Сначала в базе данных создается новая таблица DogovorXXXX, где
XXXX обозначает тот год, записи о договорах которого будут
архивироваться.

Затем все записи о договорах за указанный год копируются из
таблицы Dogovor в таблицу DogovorXXXX.
 Все скопированные записи о договорах за указанный год удаляются из
таблицы Dogovor.
Проблема здесь заключается в том, чтобы отменить всю транзакцию при неудачном
выполнении какой-либо ее операции. Нам не нужна новая таблица, если в нее нельзя
скопировать данные. Не нужно архивировать данные, если они не удаляются из основной
таблицы. Аналогично, не нужно удалять никакие записи из основной таблицы, если они
не скопированы в архивную таблицу. Для решения этой задачи можно использовать
объект Transaction и методы этого объекта, позволяющие вернуть (откатить) базу данных
в исходное состояние в случае сбоя каких-то операций.
1. Создайте форму, включающую поле со списком, кнопки Ok и Cancel (рис. 1.16). Не
забудьте импортировать в код формы пространство имен System.Data.SQLClient.
2. Для кнопок введите код, представленный ниже. Обратите внимание, что процедура
обработки события Form_Load инициирует список ListBox значениями, из которых можно
выбрать год архивирования и устанавливает год по умолчанию.
Рис. 1.16. Расположение элементов управления в форме Архивные договоры
Imports
System.Data.SqlClient
Private Sub Form3_Load(ByVal sender As Object, ByVal
e
As
System.EventArgs)
Handles
MyBase.Load
ListBox1.Items.Add("2001")
ListBox1.Items.Add("2002")
ListBox1.Items.Add("2003")
ListBox1.Items.Add("2004")
ListBox1.SelectedIndex
=
0
End
Sub
Private
Sub
Button2_Click(ByVal
sender
As
System.Object, ByVal e As System.EventArgs) Handles
Button2.Click
Me.Close()
End
Sub
Private
Sub
Button1_Click(ByVal
sender
As
System.Object, ByVal e As System.EventArgs) Handles
Button1.Click
Dim
sql
As
String
Dim
result
As
Integer
Dim
records
As
Integer
Dim
SelectedYear
As
String
Dim cnn As New SqlConnection("Persist Security
Info=False;Integrated
Security=SSPI;database=Dogovor;server=abrzh")
Dim
cmd
As
New
SqlCommand
Dim
trans
As
SqlTransaction
SelectedYear
=
ListBox1.SelectedItem
'Открытие объекта Connection и запуск транзакции
cnn.Open()
trans
=
cnn.BeginTransaction
'Включение
команды
в
транзакцию
cmd.Connection
=
cnn
cmd.Transaction
=
trans
'Указание
команды
SQL
для
вставки
соответствующих записей в архивную таблицу
sql = "SELECT * INTO Dogovor" & SelectedYear & _
" From Dogovor WHERE year(dogovorDate)= " &
SelectedYear
'Передача текста команды SQL в транзакцию
cmd.CommandText
=
sql
result
=
cmd.ExecuteNonQuery
'Отображение результатов вставки записей в
архивную
таблицу
If
result
>
0
Then
records
=
result
MsgBox(records & "записей вставлено в таблицу
успешно
за
"
&
SelectedYear)
Else
MsgBox("Записи не вставлены в таблицу за " &
SelectedYear)
'при отсутствиии записей транзакцию следует
прекратить
trans.Rollback()
End
If
If
records
>
0
Then
'Удаление
записей
из
исходной
таблицы
sql
=
"DELETE
FROM
Dogovor
WHERE
year(dogovorDate)="
&
SelectedYear
'Эта команда находится в той же транзакции
cmd.CommandText
=
sql
result
=
cmd.ExecuteNonQuery
'Показать
результаты
удаления
If
result
=
records
Then
MsgBox(records
&
"записей
удалено")
'Все действия усрешно выполнены. Фиксируем
транзакцию
trans.Commit()
Else
MsgBox("Записи
не
удалены")
End
If
Else
End
If
cnn.Close()
End
Sub
End Class
Поскольку транзакции определяются на уровне подключения, то сначала нужно открыть
подключение, а затем создать объект Transaction с помощью вызова метода
BeginTransaction для открытого подключения. Объекты Connection и Transaction
присваиваются объекту Command, который будет использоваться для выполнения команд
по отношению к базе данных.
Первые два этапа создания архивной таблицы и копирования выбранных строк
выполняются с помощью одной команды SELECT, которая содержит предложение INTO
имя_таблицы. Указанная таким образом таблица создается автоматически, а если такая
таблица уже существует, то генерируется исключительная ситуация. Выбранное значение
года добавляется к имени таблицы Dogovor для создания имени новой архивной таблицы.
Команда SELECT INTO не создает индекс, если он существует в исходной таблице.
Для повышения производительности выполнения запросов по отношению к данной
таблице, вероятно, придется создавать индексы по одному или нескольким полям.
Для выполнения команды SQL вызывается метод ExecuteNonQuery(), который возвращает
количество охваченных запросом записей. Если это возвращаемое значение больше нуля,
следовательно, нужные записи найдены и вставлены в новую таблицу. В противном
случае это значит, что таблица не может быть создана либо для копирования не найдено
никаких записей.
В любом из этих случаев транзакция откатывается, даже если таблица создана, чтобы база
данных не наполнялась пустыми и бесполезными таблицами.
Если хотя бы одна запись скопирована в таблицу, то ее прототип в исходной таблице
Dogovor удаляется с помощью команды DELETE, содержащей предложение WHERE с
заданным годом. В случае успешного выполнения этой команды, то есть, если количество
скопированных и удаленных строк совпадает, транзакция считается успешно завершенной
и фиксируется.
В противном случае, то есть, если какая-то отдельная операция завершается неудачно
(нарушится процесс удаления записей, будет отменено разрешение на удаление
архивируемых данных или произойдет сбой сервера), вся транзакция будет отвергнута.
Откат транзакции гарантирует, что при неудачной попытке удаления корректных записей
из таблицы Dogovor архивная таблица DogovorXXXX будет удалена.
Самостоятельно
3. Добавьте в таблицу Dogovor поле dogovor_Data для хранения даты
договора и внесите в него информацию. Выполните все описанные выше
действия и поэкспериментируйте с этим приложением, создавая архивы
для
записей
разных
лет.
4. Для проверки полученных результатов сопоставьте содержимое новой
архивной и исходной таблиц до и после архивирования (рис. 1.17).
Рис. 1.17. Содержание исходной таблицы до начала архивирования, исходной и
архивной таблиц после завершения архивирования
Download