Доступ к данным посредством ADO.NET - 11 Февраля 2010 - Лекции
Четверг, 08.12.2016, 05:02
Приветствую Вас Гость | RSS

Лекции

Меню сайта
Форма входа
Категории раздела
ТАУ (Теория автоматического управления) [31]
лекции по ТАУ
Экология [151]
учебник
Бухгалтерский учет и налогообложение в строительстве [56]
Дементьев А.Ю. - Практическое пособие
Психология [104]
Пип
информатика [80]
с# Карли Ватсон
современные стулья [0]
новинки
Поиск
Главная » 2010 » Февраль » 11 » Доступ к данным посредством ADO.NET
00:43
Доступ к данным посредством ADO.NET
Доступ к данным
посредством ADO.NET
В предыдущей главе рассматривалось, каким образом мастера и генерирующие
код инструменты, входящие в состав Visual С#, могут быть использованы при со-
здании пользовательских интерфейсов и управляющих элементов для доступа к ре-
ляционным базам данных.
В настоящей главе будет рассматриваться реализация такого же доступа к дан-
ным с помощью кода, написанного непосредственно программистом, а не сгенери-
. рованного мастером. Для реализации такого подхода следует воспользоваться
классами ADO.NET доступа к данным. Сначала сделаем небольшой обзор самого
ADO.NET, затем перейдем к изучению структуры классов, входящих в ADO.NET,
и, наконец, создадим несколько примеров программ, которые используют
ADO.NET.
4 T O T a K o e A D O . N E T ?
Под названием ADO.NET объединено множество классов, которые использу-
ются совместно с С# и Microsoft .NET Framework для осуществления доступа
к данным, хранящимся в реляционном таблично-ориентированном формате. Сюда
относятся реляционные БД Microsoft Access и SQL Server, а также некоторые
и даже нереляционные источники данных. Система ADO.NET входит в состав
• . .NET Framework и разработана специально для использования с языками програм-
мирования .NET, и прежде всего с С#.
ADO.NET находится в модуле System.Data.dll. (Более подробное описание на-
званного модуля СМ. В главе 21.) В некотором СМЫСЛе МОДУЛЬ System.Data.dll
••..':_ и есть ADO.NET, поскольку любой класс, содержащийся в этом модуле, по опре-
делению представляет собой составную часть ADO.NET. Сюда включены все клас-
сы пространства имен System.Data И ОДИН КЛаСС ИЗ пространства имен System.Xml.
XML рассматривался в предыдущей главе, и в настоящей главе мы продолжим
изучать поддержку, которую ADO.NET оказывает XML.
Откуда взялось название ADO.NET?
Возникает вопрос: откуда у этой составной части .NET Framework взялось такое
загадочное название — ADO.NET? Почему бы не назвать его просто System.Data?
Название ADO.NET происходит от названия ADO (ActiveX Data Objects, объекты
данных ActiveX), широко используемого в предшествующих поколениях технологий
компании Microsoft множества классов, предназначенных для доступа к данным.
Доступ к данным посредством ADO.NET 517
Имя ADO.NET используется, чтобы подчеркнуть, что данный интерфейс является
наиболее предпочтительным при осуществлении доступа к данным в среде про-
граммирования .NET.
ADO.NET используется для тех же целей, что ADO, и предоставляет множест-
во очень простых в использовании классов, предназначенных для осуществления
доступа к данным, обновленным и расширенным для использования в среде про-
граммирования .NET. Хотя ADO.NET выполняет те же функции, что и ADO, ощако
классы, свойства и методы в ADO.NET существенно отличаются от используемых
в ADO.
Цели, преследовавшиеся при создании ADO.NET
Эти цели включают: осуществление простого доступа к реляционным и нереля-
ционным данным, унификация доступа к реляционным и XML-данным, поддержка
многозвенных приложений в Интернете, а также возможность расширения, кото-
рая бы позволила поддерживать большее количество различных источников дан-
ных, чем допускалось предшествующими технологиями.
Простота доступа к реляционным данным
Основной целью при создании ADO.NET было обеспечение простого доступа
к реляционным данным. Несложные в использовании классы представляют табли-
цы, столбцы и строки, применяемые в реляционных базах данных. Кроме того,
в ADO.NET вводится класс DataSet, который представляет набор данных, извле-
ченных из связанных таблиц, в виде единого объекта, благодаря чему удается со-
хранить целостность структуры отношений между ними. Это новый подход,
привнесенный ADO.NET, позволяет существенно расширить возможности интер-
фейса доступа к данным.
Расширяемость
ADO.NET является расширяемой системой — она представляет собой каркас,
куда могут включаться различные провайдеры данных .NET (называемые также
управляемыми провайдерами), которые могут создаваться для чтения и записи
данных из самых разнообразных источников. ADO.NET поставляется с двумя
встроенными провайдерами данных .NET, один из которых предназначен для ис-
точников данных OLE DB, а другой — для источников данных Microsoft SQL Server.
OLE DB позволяет осуществлять доступ к данным, хранящимся в форматах Microsoft
Access, базах данных сторонних производителей и нереляционных данных. Кроме
того, компания Microsoft недавно сделала предварительное сообщение о провайде-
ре данных ODBC.NET для ADO.NET, который призван существенно расширить
возможности осуществления доступа из .NET к еще большему числу унаследован-
ных форматов данных и базам данных, разработанных сторонними организациями.
Поддержка многозвенных приложений
ADO.NET рассчитана на поддержку многозвенных приложений. Названная ар-
хитектура является на сегодняшний день наиболее распространенной для бизнес-
приложений и приложений электронной коммерции. Многозвенная архитектура
предполагает выполнение различных логических частей приложения на нескольких
серверах или в рамках нескольких различных процессов, каждая из которых назы-
вается звеном.
518 Глава 19
В ADO.NET для осуществления взаимодействия между звеньями используется
открытый Интернет-стандарт XML-формата, который позволяет данным преодоле-
вать защиту, используемую в Интернете, и допускает реализацию одного или не-
скольких звеньев, не подчиняющихся стандартам компании Microsoft.
Унификация доступа к реляционным и XML-данным
Другое не менее важное предназначение ADO.NET — это обеспечение мости-
ка между реляционными данными, хранящимися в виде строк и столбцов, и XML-
документами, представляющими иерархическую структуру данных. .NET-технология
построена на основе XML, и в ADO.NET она находит самое широкое применение.
Перейдем к непосредственному рассмотрению классов, из которых состоит
ADO.NET.
Обзор классов и объектов ADO.NET
На изображенной ниже диаграмме представлены основные классы ADO.NET.
Данная диаграмма не является диаграммой наследования, на ней всего лишь пока-
заны отношения между наиболее широко используемыми классами:
Объекты-потребители A0O.NET
DataSet
-*> DataTable


DataRow
DataColumn
1— •! DataRelation
Объекты-провайдеры данных .NET
Connection
Command
CommandBuilder
DataReader
DataAdapter
Объекты-провайдеры специфичны для каждого конкретного типа источника
данных; реальные считывание и запись данных из соответствующего источника
осуществляются с помощью объектов-провайдеров, специфичных для данного ис-
точника. Объекты-потребители — это объекты, которые используемые для осуще-
ствления доступа и выполнения манипуляций над данными, после того как эти
данные считаны в память. Для работы объектов-потребителей не требуется нали-
чия установленного соединения; с данными, находящимися в памяти, можно рабо-
тать, даже если соединения с базой данных более не существует. Для работы
объектов-провайдеров активное соединение оказывается необходимым; прежде
всего, эти объекты используются для считывания необходимых данных в память,
затем — в зависимости от того, что требуется с ними сделать,— вы выполняете
над ними соответствующие манипуляции в памяти с использованием объектов-
потребителей и/или обновляете данные в источнике данных, используя объекты-
провайдеры для записи изменений в источник данных.
Доступ к данным посредством ADO.NET 519
Объекты-провайдеры
Эти объекты определяются для каждого провайдера данных .NET. Их имена
предваряются некоторым именем, уникальным для данного провайдера; так, на-
пример, фактическое имя объекта, представляющего собой соединение, для про-
вайдера OLE DB—oleDbConnection, для провайдера .NET для SQL Server
используется класс sqiconnection, а при соединении, устанавливаемом провайде-
ром .NET ODBC, Класс НОСИТ ИМЯ OdbcConnection.
Объект Connection
Объект Connection — это первый из объектов, который вы будете использо-
вать; необходимость в нем возникает до начала применения всех остальных объек-
тов ADO.NET. Он обеспечивает установление основного соединения с вашим
источником данных. Если используется база данных, которой требуется передавать
имя пользователя и пароль, или база данных, расположенная на удаленном сете-
вом сервере, то все действия по установлению соединения с базой данных и реги-
страции в ней берет на себя объект connection.
Если вы знакомы с классическим ADO, то вы, вероятно,
обратили внимание на то, что объект connection
и другие объекты, выполняющие аналогичные функции
в классическом ADO, в ADO.NET имеют аналогичные имена.
Объект Command
Этот объект используется для передачи команды, такой как SQL-запрос, источ-
нику данных, например, 'SELECT * FROM Customers*, которая запрашивает данные,
находящиеся в таблице Customers. Имена таких объектов специфичны для разных
провайдеров; для SQL Server этот объект носит имя Sqicommand, а для OLE DB —
OleDbCommand.
Объект CommandBuilder
Этот объект используется для создания SQL-команд, которые позволяют моди-
фицировать хранящиеся в объектах данные, полученные из одной таблицы. Этот
объект будет рассматриваться более подробно в разделе, посвященном внесению
изменений в данные. Среди названий этого объекта, имеющих отношение к конк-
ретным провайдерам,— SqlCommandBuilder ДЛЯ SQL Server И OleDbCommandBuilder
для OLE DB.
Объект DataReader
Это очень быстрый и простой в использовании объект, считывающий поток
данных в режиме "только вперед" и "только чтение" (например, множество най-
денных заказчиков) из источника данных. Этот объект обеспечивает максимальное
быстродействие при простом считывании данных; образец использования этого
объекта можно найти в первом из приведенных ниже примеров. Среди специфич-
ных ДЛЯ КОНКреТНЫХ прОВаЙДерОВ названий ЭТИХ Объектов — SqlDataReader ДЛЯ
SQL Server И OleDbDataReader ДЛЯ OLE DB.
520 Глава 19
Объект DataAdapter
Это многоцелевой класс, который выполняет различные операции, специфич-
ные для конкретного источника данных, включая обновление измененных данных,
наполнение наборов данных (см. ниже) и другие действия, которые встретятся нам
в последующих примерах. Среди специфичных для конкретных провайдеров названий
ЭТИХ объектов — SglDataAdapter ДЛЯ SQL Server И OleDbDataAdapter ДЛЯ OLE DB.
Объекты-потребители
Это объекты, использующиеся со стороны ADO.NET при разорванном соединении.
Объект DataSet
Этот объект представляет собой семейство связных таблиц, к которым прило-
жение может обращаться как к единому целому. Например, таблицы customers,
orders и Products могут находиться в одном и том же объекте DataSet, представ-
ляя каждого из клиентов и продукцию, которую данный клиент заказал в вашей
компании. При помощи такого объекта можно быстро извлекать все необходимые
данные из каждой таблицы, анализировать их и вносить соответствующие измене-
ния, пока соединение с сервером не установлено, а затем сохранять все изменения
на сервере посредством одной эффективной операции.
Объект DataSet обладает свойствами, которые позволяют осуществлять доступ
к объектам более низкого уровня, представляющим отдельные таблицы, строки,
столбцы и отношения. Вот эти объекты:
Объект DataTable
Представляет отдельные таблицы, хранящиеся в объекте DataSet, например,
Customers, Orders ИЛИ Products.
Объект DataColumn
Представляет каКОЙ-ЛИбо Столбец В таблице, например, CustomerName ИЛИ OrderlD.
Объект DataRow
Представляет какую-либо связную строку данных из некоторой таблицы, на-
пример, customeriD, имя, адрес и т. д. для какого-либо конкретного пользователя.
Объект DataRelation
Представляет отношение между двумя таблицами, устанавливаемое посредством
общего столбца; так, например, в таблице orders может присутствовать столбец
CustomeriD, позволяющий определить, кто из клиентов разместил данный заказ.
Помимо перечисленных здесь в ADO.NET существуют и некоторые другие объ-
екты, однако на данный момент мы не будем углубляться в детали, а перейдем
к рассмотрению некоторых примеров, демонстрирующих, как все это работает.
Использование пространства имен System.Data
Первым шагом на пути к использованию ADO.NET из кода на С# является
ссылка на пространство имен System.Data, в котором находятся все классы
ADO.NET. В начале каждой программы, в которой будет использоваться
ADO.NET, необходимо использовать директиву using следующего вида:
: using System.Data;
Доступ к данным посредством ADO.NET 521
Провайдер данных .NET для SQL Server
Затем необходимо сослаться на провайдер данных .NET, применяемого для того
источника данных, которым вы планируете воспользоваться. Если используется
SQL Server (версии 7 или выше) либо MSDE, то наилучшее быстродействие
и наиболее прямой доступ ко всем имеющимся возможностям осуществляется
с помощью провайдера данных .NET, предназначенного для SQL Server, для обра-
щения к которому используется следующая директива using:
using System.Data.SqlClient;
Провайдер данных .NET для OLE DB
Для большинства,5источников данных, отличных от SQL Server (Microsoft Access,
Oracle и некоторых других), следует использовать провайдер данных .NET, пред-
назначенный для OLE DB, для обращения к которому необходимо использовать
директиву using:
using System.Data.OleDb;
Если есть провайдер данных .NET, специально предназначенный для использу-
емой базы данных, то может появиться вполне законное желание воспользоваться
именно этим провайдером, для чего придется применить соответствующую дирек-
тиву using. Провайдер данных .NET для SQL Server представляет собой пример
провайдера, очень чувствительного к типу используемого продукта.
Провайдер данных .NET для ODBC
Если вы работаете с каким-либо источником данных, для которого не существует
"родного" провайдера или провайдера OLE DB (как, например, для PostgreSQL или
некоторых других баз данных, созданных сторонними организациями), то наилуч-
шей альтернативой является провайдер данных .NET для ODBC. Он представляет
собой отдельный загрузочный модуль в Visual Studio.NET (находящийся по адресу
http://msdn.microsoft.com/downloads/) — в .NET Framework следует найти ODBC
.NET Data Provider Beta. После инсталляции загружаемого модуля он включается
в состав модуля system.Data.odbc.dll; при компиляции на этот модуль необходи-
мо специально сослаться. Обратиться к провайдеру ODBC можно с помощью ди-
рективы using:
using System.Data.Odbc;
Практикум: простой пример осуществления доступа к данным,
хранящимся в одной таблице
В этом примере мы попытаемся извлечь некоторые данные из одной таблицы,
например, из таблицы customers, используемой в качестве образца базы данных
SQL Server/MSDE Northwind — той же самой базы данных, которую мы рассмат-
ривали в предыдущей главе.
Эта таблица состоит из строк и столбцов, в которых содержится информация
о клиентах торговых представителей компании Northwind. В Visual Studio.NET эта
таблица выглядит так, как показано на следующем рисунке.
Создадим с помощью ADO.NET программу, которая будет запрашивать столб-
цы данной таблицы С именами CustomerlD И CompanyName.
522 Глава 19
>
щ
' • •
I
S B
A & T O &
3 t A w 5
8 L C N P
8 O U 0
вот ж
« V
CACTU
Ш1ТС"'
CHOPS
COMMI
и
Aritco ,uerva
idslpereetMs
U-io Corn d « г-'cp-v id-5?
BcUom Do;^f Кv'- -У< 5
B's Sever ages
C&Zlv*. < • -ni- •• : ',ili*;v«jr
Ceniro corner с id? «'Vxtc-гигпй
ChQp-vJ»Y Chines»
C ^ w wne.ro
!Cor.t*:tf^me
;$*$&& Aode*$
•S Ала Тги; о
Artcrw f c f e w
Licence Lee h:<".
;;f|2 j 2bethUncca
Frafjcwco Ch£>-;.
Yanq Wang
S»4s Repfft*c««<^ive
Ordtf Adf№ аг<*!о?
Acccv:nbng Mor^g^r
5б!е$ 'Repres«Haitive
Sctes Agent
^ Owiu*?
A^Ci. d-u - ' -A u:.- 2222
Fen: ^?tr, 57
12., T-i-3 des ©otscbers
• f-'-tvi croy '>ccs
Се; Ы rv-0
5swr« <fe Granadj 9993
hteUPtstr. 29
'•';.<.;.:Si. j
London
Strasfeeufg
Tsawess««
London
Mexico C f . V.;: j
•Bern .••:*•
Project Types:
C:J Vtswd Bask: FVojects
p| S-tup an*d Depleyment Rro|ecb
•• Ll Ol^ Projc:t$
^LJ Visual Studo Solutions
Данная программа, а также все после-
дующие примеры в этой главе, будут созда-
ваться одним и тем же способом — в виде
проекта консольного приложения Visual
Studio.NET; для этого и всех последующих
примеров в настоящей главе следует ис-
пользовать приведенную ниже последова-
тельность шагов для компиляции и запуска
приложения.
Запустите Visual Studio.NET и создайте
новый проект С#. Для этого выберите
пункт File | New | Project... основного меню,
затем выберите шаблон Console Application
из меню Visual C# Projects. Назовите вновь
создаваемую программу DataReaderExample
(см. рис. слева).
Переименуйте файл Classl.cs В DataReaderExample.cs, а затем ПОЛНОСТЬЮ ВВе-
дите следующую программу С#, которая оказывается не слишком длинной:
PfOJCCt
~] S;cv.'><.".
using System;
using; System. Data;
using System,Data;SqlGlient;
class DataReaderExample
{ ' . . •
public static void Main0
•/•/ Использование пространства имен AD0.NET
//Использование пространства
•//• имен провайдера данных SQL Server
//Задание строки соединения специально для SQL Server
SqlConnection thisConnection ~ new SqlConnection{
©"Data Source-(local);Integrated Security-SSPI; " +
яInitial Catalog=northwind'f) ;
//Установка соединения
thisConnection.Open();
// Создание команды для данного соединения
SqlCommand thisCommand = thisConnection.CreateCommandO;
//Задание SQL-запроса для этой команды
thisCommand.CommandText = •
*SELECT CustomerlD/ CompanyName FROM Customers";
//Выполнение объекта DataReader для заданной выше команды
SqlDataReader thisReader = thisCommand.ExecuteReader();
Доступ к данным посредством ADO.NET 523
II Пока имеются непрочитанные строки
while (thisReader.ReadO )
{
// Вывод столбцов с ID и именами .
Console.Writebine(*\t{0}\t{1}",
thisReader[ "CustomerJDW3 , thisReader [*CompanyName*
// Закрытие объекта считывания
thisReader .Close () ; V :./.
II Закрытие соединения
thisConnection.Close();
Откомпилируйте эту программу (F7) и запустите ее (Ctrl-F5). Вы увидите спи-
сок идентификаторов клиентов и названий компаний, который приводится ниже:
ALFKI Alfreds Futterkiste
ANATR Ana Trujillo Empredados у helados
ANTON Antonio Moreno Taqueria
AROUT Around the Horn
BERGS Berglunds snabbkop
BLAUS Blauer See Delikatessen
Мы пройдем по каждой строке примера, для того чтобы понять, каким образом
были получены такие результаты.
Как это работает
Первым шагом необходимо сослаться на пространство имен System.Data и на
наш провайдер — так, как это описывалось ранее. В этих примерах мы будем ис-
пользовать провайдер .NET для SQL Server, поэтому в начале программы должны
быть помещены следующие строки:
using System.Data;
using System.Data.Sgl;
Установление соединения с источником данных
Далее необходимо установить соединение со нашим источником данных. Это
осуществляется посредством создания объекта соединения с использованием строки
соединения. Строка соединения — это символьная строка, в которой содержится
имя провайдера базы данных, с которой устанавливается соединение, необходимая
регистрационная информация (пользователь базы данных, пароль и т.д.) и имя
конкретной базы данных, с которой вы собираетесь работать. Мы подробно рас-
смотрим отдельные части этой строки соединения, однако не следует забывать
о том, что эти строки для разных провайдеров существенно отличаются друг от
друга, поэтому необходимо включать в них информацию, специфичную для исполь-
зуемого провайдера данных, если ваш провайдер отличается от рассматриваемого
в настоящем примере. (Доступ к данным демонстрируется ниже в данной главе.)
Строка, в которой происходит создание объекта соединения, выглядит следую-
щим образом:
SqlConnection thisConnection = new SqlConnection(
@"Data Source=(local);Integrated Security=SSPI;и +
"Initial Catalog=northwindlf) ;
524 Глава 19
Sqiconnection — это имя объекта соединения провайдера данных .NET для SQL;
если бы мы использовали OLE DB, то пришлось бы создавать объект с именем
oieDbconnection. Строка соединения состоит из поименованных вхождений, отде-
ленных одно от другого точкой с запятой. Первым является следующее:
Data Source=(local);
Это имя SQL Server, к которому осуществляется доступ, (local) —удобное
сокращение имени SQL Server, обозначающего экземпляр сервера, который вы-
полняется на вашей машине; это имя должно сработать прямо в таком виде.
Шаблоны .NET Framework SDK допускают опционную инсталляцию настольного
средства SQL Server (называемого также MSDE) для выполнения шаблонов. По
умолчанию этому экземпляру присваивается имя (local) \NetSDK. Следовательно,
в качестве альтернативы можно попытаться использовать следующее имя сервера:
Data Source=(local)\NetSDK;
Обратите внимание на то, что знак @, расположенный в начале строки соеди-
нения, обозначает, что это — символьное значение, что позволяет использовать
в строке обратный слэш; в противном случае, для того чтобы использовать символ
обратного слэша в строке С#, необходимо применять escape-последовательность,
состоящую из двух обратных слэшей (\\). Можно также указать фактическое имя
компьютера:
Data Source=ROADRUNNER\NetSDK;
Если тот Server, с которым вы работаете, инсталлирован, то известно имя эк-
земпляра SQL Server. В противном случае придется обратиться к вашему админи-
стратору SQL Server или сетевому администратору и узнать имя, которое следует
использовать.
Следующая часть строки соединения определяет, как регистрироваться в базе
данных; эта специальная фраза указывает на использование встроенной объеди-
ненной системы безопасности для регистрации в Windows и в SQL Server, поэтому
не требуется задавать дополнительных имен и паролей:
Integrated Security=SSPI;
SSPI расшифровывается как Security Support Provider Interface (интерфейс
провайдера по обеспечению безопасности); это обозначает встроенную стандарт-
ную систему обеспечения безопасности для Windows и SQL Server. В завершение
указывается конкретная база данных, которую мы собираемся использовать,—
в данном случае это база данных Northwind:
Initial Catalog=northwind
Используемая в качестве образца база данных Northwind по умолчанию всегда
присутствует в инсталляции SQL Server, хотя многие администраторы баз данных
предпочитают опускать ее из соображений экономии места. Остальная часть про-
граммы работает в точности так же, как и в предшествующем примере, поэтому
мы не будем повторяться.
Мы обладаем объектом соединения, настроенным на соответствующий компью-
тер и базу данных (это соединение пока не является активным; для активизации
его необходимо открыть).
Метод Open
Как только появляется объект соединения, первое, что требуется сделать,—
это открыть его, в результате будет установлено соединение с базой данных:
thisConnection.0pen() ;
Доступ к данным посредством ADO.NET 525
Если выполнение метода open о завершится неудачей, например, не удалось
обнаружить необходимый SQL Server, то будет сгенерирована исключительная си-
туация sqiException и будет выведено следующее сообщение:
Unhandled Exception: System.Data.SqICIient.SqIException: Timeout expired.
(Необрабатываемая исключительная ситуация: System.Data.SqICIient.SqIException:
Истекло время ожидания.)
Possible reasons: timeout period elapsed prior to completion of the operation,
(Возможные причины: период ожидания истек раньше, чем была завершена операция,)
the server is not responding, or the maximum pool size was exceeded.
(сервер не отвечает, превышено максимальное значение пула.)
Please see the documentation for further details.
(За дополнительными подробностями обращайтесь к документации.)
at System.Data.SqlClient.SqlConnection.OpenQ
at DataReaderSqlExample.Main() in c:\begsharp\chapter19\datareaderexample\
datareaderexample.cs:line 15
Данное сообщение свидетельствует о том, что программа не может установить
соединение с указанным SQL Server за приемлемое время. Убедитесь в том, что
имя сервера в строке соединения не содержит ошибок.
Отправка запроса (SQL-команды)
На следующем этапе необходимо создать командный объект и передать ему
SQL-команду для выполнения операции с базой данных (например, для извлечения
некоторых данных). Вот код, который позволяет осуществить это:
SqlCommand thisCommand = thisConnection.CreateCommand();
thisCommand.CoramandText = "SELECT CustomerlD, CompanyName from Customers";
У объекта соединения имеется метод createCommandO, предназначенный для
создания команды, привязанной к установленному соединению, именно это и исполь-
зуется для получения командного объекта. Сама команда присваивается свойству
командного объекта commandText. Нам требуется получить список идентификато-
ров клиентов и имен компаний, хранящихся в базе данных Northwind, в соответст-
вии с этим создается команда SQL-запроса:
SELECT CustomerlD, CompanyName from Customers
Команда SELECT — это SQL-команда, позволяющая извлекать данные из одной
или нескольких таблиц. Весьма распространенными являются ошибки, заключаю-
щиеся в неправильном наборе имен таблиц, что приводит к возникновению другой
исключительной ситуации:
thisCommand.CommandText = "SELECT CustomerlD, CompanyName from Customer*;
Стоп! В названии таблицы Customers пропущена буква s. Это приводит к воз-
никновению следующей исключительной ситуации:
Unhandled Exception: System.Data.SqICIient.SqIException: Invalid object name 'Customer1...
(Необрабатываемая исключительная ситуация: System.Data.SqICIient.SqIException:
Неправильное имя объекта 'Customer'...)
Возможно, вы обратили внимание на то, что метод, сгенерировавший ошибку,
называется ExecuteReader (); чтобы получить результаты, необходимо создать объ-
ект DataReader И ВЫПОЛНИТЬ Команду.
526 Глава 19
Считывание результатов с помощью объекта DataReader
Объект DataReader — это простой, быстрый объект, предназначенный для не-
медленного получения результатов запроса. Он работает в режиме "только чтение",
поэтому его нельзя использовать для внесения изменений в данные — к рассмот-
рению данного вопроса мы перейдем после этого примера. Как видно из предыду-
щего раздела, мы используем метод из последнего созданного нами объекта —
командного объекта — для создания привязанного объекта, который потребуется
нам в дальнейшем, в данном случае это объект DataReader:
SqlDataReader thisReader = thisCoiranand.ExecuteReader () ;
Метод ExecuteReader () осуществляет выполнение SQL-команды в базе данных,
поэтому все ошибки базы данных генерируются именно на этом этапе; этот же ме-
тод создает объект для считывания полученных результатов. Именно этот объект
вместе с содержащимися в нем результатами передается нашей программе; мы
Присваиваем его Объекту thisReader.
Методы Read и Get
Есть несколько различных методов для извлечения результатов из объекта счи-
тывания. Метод Read () объекта DataReader производит считывание отдельной
строки данных, полученных в результате выполнения запроса, и возвращает значе-
ние true, если там еще есть непрочитанные данные, и false в противном случае.
Поэтому мы организовываем цикл while для считывания данных с помощью мето-
да Read () и выводим результаты по мере их получения на каждой итерации:
while (thisReader.Read())
{
Console.WriteLine(*\t{0}\t{l}w,
thisReader["CustomerlD"], thisReader["CompanyName*]);
}
Пока метод Read О возвращает Значение true, функция Console. WriteLine('\t{O}\t{l}#
выводит строки, каждая из которых состоит из двух элементов, разделенных сим-
волами табуляции (\t). Объект OleDbDataReader обладает СВОЙСТВОМ indexer (об-
суждение индексаторов можно найти в главе 11). Индексатор позволяет обращаться
К столбцам как К Элементам массива ПО ИХ Именам: thisReader [ "CustomerlD" ] ,
thisReader ["CompanyName"]. В результате ПРОИСХОДИТ ВЫВОД значений CustomerlD
И CompanyName."
ALFKI Alfreds Futterkiste
ANATR Ana Trujillo Empredados у helados
Когда метод Read о достигает последнего значения, он возвращает значение
false и выполнение цикла while завершается.
Закрытие объектов Reader и Connection
Последним шагом является закрытие объектов, в число которых входят Reader
и connection. У каждого их них имеется свой собственный метод, к которым мы
обращаемся, перед тем как закончить выполнение программы:
thisReader.Close();
thisConnection.CloseO ;
Вот и все, что касается осуществления доступа к одной таблице!
Доступ к данным посредством ADO.NET 527
Практикуй: пример с использованием Microsoft Access
Эта же программа с незначительными изменениями может использоваться для
доступа к той же БД в версии Microsoft Access (nwind.mdb). Она располагается
В директории C:\Program Files\Microsoft Visual Studio Net\Common7\Tools\Bin,
однако эту базу данных не следует использовать непосредственно — ее необходимо
предварительно скопировать (например, во временную директорию C:\tmp\nwind.mdb),
для того чтобы в любой момент вернуться к исходному варианту. Кроме того сле-
дует учитывать, что этот путь использовался в ранней версии Visual Studio, однако
к моменту чтения данного раздела он мог измениться, в таком случае следует вос-
пользоваться командой search, если вы не смогли найти ее в указанном месте.
Все эти изменения — за исключением отдельных деталей строки соединения —
будут работать для любых источников данных O L E DB. Рассмотрим пример. (Этот
пример хранится под названием DataReaderAccessExampie на web-сайте издатель-
ства Wrox.)
using System;
using Systeiii.Data;
using System.Data.OleDb;
class DataReader^ccessExample
{
public static void Main(}
'•'//•• Использование пространства имен ADO.NET
// Использование пространства имен
// для провайдера данных OLE DB .NET
// все действия выполняются в функции Main{)
// Создание объекта сое^данения для провайдера OLE DB: Microsoft Access;
// обратите внимание на символ @, предваряющий символьное значение
// строки, который делает возможным использование обратных слэшей
OleDbConnection thisConnection - new QleDbConnection(
@"Provider=Microsoft.Jet,OLEDB.4.0;Data Source=C:\tmp\nwind.mdbM),
// Открытие объекта соединения
thisConnection,Open();
//Создание объекта SQL-команды для данного соединения
OleDbCommand thisCommand = thisConnect-.ion.CreateCcirmarj.dO;
;/ / Ишщиализация команды SQL SELECT, предназначенной
// для извлечения необходимых данных
thisCommand.CommandText ~
•SELECT CustomerID, CompanyName FROM Customers';
// Создание объекта DataReader на основе предварительно
//определенного; командного объекта :
OleDbDataReader thisReader•;= thisCommand.ExecuteReader();
while {thisReader.Read())
{
Console.WriteLine(*\t{0}\t{l}lf, thisReader ["CustomerlD"] ,
thisReader[•CompanyName"]);
}
thisReader.Close(); . .
thisConnection.Close(); :
Все сделанные изменения касаются только имен объектов и содержимого стро-
ки соединения.
528 Глава 19
на
Кроме того, директива using, определяющая провайдер данных, изменилась с
using System.Data.SqlClient;
using System.Data.OleDb;
Как это работает
Вместо Объектов SqlConnection, SqlCommand И SqlDataReader МЫ создаем объ-
екты OleDbConnection, OleDbCommand И OleDbDataReader. Эти объекты работают,
в основном, так же, как и их аналоги для OLE DB; если вас интересуют тонкие от-
личия в их работе, то вы можете обратиться к документации по Visual Studio.NET.
Единственное отличие касается строки соединения, которую пришлось изменить
полностью. Ее первая часть, состоящая из посылки Provider, определяет провай-
дера, используемого для данного типа БД. Для баз данных Microsoft Access этот
провайдер всегда имеет имя ("Jet" — это имя процессора базы данных, включен-
ного в Access):
Provider=Microsoft.Jet.OLEDB.4.0;
Если потребуется воспользоваться другим провайдером OLE DB для какой-либо
базы данных или другого формата данных, то имя провайдера должно задаваться
именно В предложении Provider.
Вторая часть строки соединения представляет собой предложение Data source,
и для OLE DB/Microsoft Access оно просто определяет имя файла, в котором на-
ходится база данных Microsoft Access (файл с расширением .mdb) и который необ-
ходимо открыть:
Data Source=C:\tmp\nwind.mdb
Обратите внимание на то, что знак @, предваряющий строку соединения
в программе, определяет символьное значение строки в С#, что позволяет исполь-
зовать в имени пути символ "обратный слэш"; в противном случае для задания
имен файлов в С# потребовалось бы использовать escape-последовательность
в виде двух обратных слэшей (\\).
Практикум: внесение изменений в данные
Теперь мы умеем считывать информацию из баз данных, но каким образом
можно вносить изменения в эти данные? Приведем очень простой пример, в кото-
ром работа ведется с единственной таблицей, однако он позволит ввести несколь-
ко новых объектов, которые мы будем использовать в этой главе позднее.
Предположим, что один из наших клиентов — Bottom-Dollar Markets — изме-
нил свое название на Acme, Inc. Требуется изменить название компании в базе
данных. В этом примере мы снова воспользуемся базой данных Northwind, пред-
ставленной в версии SQL Server/MSDE.
Полный исходный код представлен ниже (этот пример можно переписать — он
хранится ПОД именем DataUpdateExample):
using System;
using System.Data;
using System.Data.SqlClient;
class DataUpdateExample
//Использование пространства имен AD0.NET
//Использование провайдера
// данных .NET SQL Server
Доступ к данным посредством ADO.NET 529
public static void Main()
{
// Задание строки соединения специально для SQL Server
• / . : SqlConnection thisCormection = new SqlConnection(
@"Data Source=(local);Integrated Security=SSPI;" +
"Initial Catalog=northwind");
// Установка соединения
thisConnection.Open();
// Создание объекта DataAdapter для внесения
// изменений и выполнения других операций
- SqlDataAdapter thisAdapter,= new SqlDataAdapter(
•SELECT CustomerID, CompanyName FROM Customers", thisConnection);
// Создание объекта CoiranandBuilder для формирования SQL-команд
SqlCoinmandBuilder thisBuilder = new SqlCommandBuilder(thisAdapter);
•••/•/• Создание объекта DataSet, предназначенного
//для хранения связанных таблиц, строк и столбцов
DataSet thisDataSet = new DataSet();
// Наполнение объекта DataSet с помощью запроса,
//определенного ранее для объекта DataAdapter
thisAdapter.Fill(thisDataSet, "Customers");
// Вывод данных до внесения изменений
Console.WriteLine(*name before change: {0}*,
thisDataSet.Tables ["Customers*]•.••Rows [9-] ["CompanyName"]) ;
// Внесение изменений в данные: таблица Customers,
// строка 9, столбец CompanyName
thisDataSet.Tables["Customers"].Rows[9]["CompanyName"] = "Acme, Inc.";
// Обращение к команде Update для внесения изменений
//в соответствующую таблицу
thisAdapter .Update•(. thisDataSet, "Customers");
Console.WriteLine("name after change: {0}",
thisDataSet.Tables["Customers"].Rows[9]["CompanyName"]);
thisConnection. CloseO;
}
В процессе выполнения программа выведет следующий выходной поток:
name before change: Bottom-Dollar Markets
(название до внесения изменений)
name before change: Acme, Inc.
(название после внесения изменений)
Теперь разберем детально исходную программу.
Как это работает
Первая часть программы аналогична предыдущему примеру; мы создаем объект
соединения с помощью строки соединения и устанавливаем само соединение:
SqlConnection thisConnection = new SqlConnection(
©"Data Source=(local);Integrated Security=SSPI;" +
"Initial Catalog=northwind");
thisConnection.Open();
530 Глава 19
Затем мы создаем объект нового типа DataAdapter:
SqlDataAdapter thisAdapter = new SqlDataAdapter(
"SELECT CustomerlD, CompanyName FROM Customers", thisCormection) ;
Объект DataAdapter ЯВЛЯетСЯ гораздо более многоцелевым, чем Объект DataReader;
этот объект используется для самых разнообразных типов операций с данными,
включая запросы, изменения и удаление. Мы инициализируем его с тем же самым
SQL-запросом, что и командный объект в предшествующем примере.
Объект CommandBuilder
В простом случае внесения изменений в единственную таблицу не требуется
знать, каким образом следует записывать SQL-команду, осуществляющую обнов-
ление ДаННЫХ; В ЭТОМ Случае МОЖНО ВОСПОЛЬЗОВаТЬСЯ удобным Объектом Command-
Builder, который автоматически построит необходимые SQL-операторы и привяжет
ИХ К Объекту DataAdapter:
SqlCommandBuilder thisBuilder = new SqlCommandBuilder(thisAdapter);
Заметьте, ЧТО МЫ передаем объект thisAdapter конструктору объекта Command-
Builder в качестве аргумента. Далее происходит создание корректных SQL-команд
и привязка их к переданному объекту DataAdapter в момент создания конструкто-
ром объекта CommandBuilder. Ниже в настоящей главе мы познакомимся и с други-
ми SQL-операторами, а пока SQL выполняет всю работу за нас.
Объект DataSet
Теперь следует ввести объект, значимость которого будет становиться очевид-
ной по мере дальнейшего обсуждения. Это объект DataSet:
DataSet thisDataSet = new DataSet();
Объект DataSet занимает центральное место в ADO.NET; он используется во
всех операциях, независимо от их сложности. В DataSet содержится набор связан-
ных объектов DataTabie, представляющих таблицы базы данных, с которой ведется
работа. У каждого объекта DataTabie имеются дочерние объекты DataRow и Data-
Coiumn, которые соответственно представляют строки и столбцы таблицы из базы
данных. Как вскоре будет видно, эти объекты позволяют осуществлять доступ ко
всем отдельным элементам таблиц, строк и столбцов.
Метод Fill объекта DataAdapter
До того как использовать объект DataSet, необходимо наполнить его данными
ИЗ баЗЫ ДаННЫХ. С ЭТОЙ Целью ИСПОЛЬЗуеТСЯ меТОД F i l l О Объекта DataAdapter.
Почему метод Fill О является методом объекта DataAdapter, а Не объекта DataSet?
Потому что DataSet является абстрактным представлением данных в памяти, в то
время как DataAdapter является объектом, который осуществляет привязку объекта
DataSet к конкретной базе данных. В качестве первого параметра методу Fill о
передается объект, который должен быть наполнен, а в качестве второго парамет-
ра — имя объекта DataTabie внутри объекта DataSet, в котором содержатся инте-
ресующие нас данные:
thisAdapter.Fi11(thisDataSet, "Customers");
В данном случае требуется таблица Customers, поэтому мы обращаемся к соот-
ветствующему объекту DataTabie в объекте DataSet с тем же именем. После того
как объект DataSet оказывается наполненным, у нас появляется возможность об-
ращаться к отдельным строкам и столбцам.
Доступ к данным посредством ADO.NET 531
Осуществление доступа к таблицам, строкам и столбцам
в объекте DataSet
Посмотрим, как выглядят данные до внесения в них изменений:
Console.WriteLine("name before change: {0}*,
thisDataSet. Tables ["Customers'] .Rows[9] ["Company-Name"]) ;
Что здесь происходит? Мы выводим столбец CompanyName из строки с индексом,
равным 9, из таблицы Customers, что приводит к получению выходного потока сле-
дующего вида:
name before change: Bottom-Dollar Markets
(название до внесения изменений)
Сложное выражение, начинающееся с thisDataSet имеет значение "Bottom-
Dollar Markets*. Рассмотрим детально, из чего оно состоит:
thisDataSet.Tables["Customers"].Rows[9]["CompanyName"]
У объекта DataSet есть свойство Tables, в котором содержится семейство всех
объектов DataTabie. Это семейство представляет собой упорядоченный список, от-
куда следует, что имеется такая возможность доступа к каждому отдельному объ-
екту DataTabie, как если бы он являлся элементом массива, при этом название
таблицы используется в качестве индекса:
Tables["Customers *]
В рамках каждого объекта DataTabie есть с
Категория: информатика | Просмотров: 1566 | Добавил: basic | Рейтинг: 0.0/0
Всего комментариев: 0
Имя *:
Email *:
Код *:
Календарь
«  Февраль 2010  »
ПнВтСрЧтПтСбВс
1234567
891011121314
15161718192021
22232425262728
Статистика

Онлайн всего: 1
Гостей: 1
Пользователей: 0

krutoto.ucoz.ru
Бесплатный конструктор сайтов - uCoz