Мастер Data Form Wizard из Visual Studio .NET позволяет быстро, буквально в несколько шагов, создать связанную с данными форму. Код, генерируемый мастером, можно будет просматривать и изменять.
Мы рассмотрим подключение к базе данных Microsoft Access BDTur_firm.mdb, которую мы создали сами. Наша задача: вывести содержимое двух связанных таблиц - "Туристы" и "Информация о туристах" на Windows-форму.
Запустите Visual Studio .NET, создайте новый проект, тип проекта - Windows Application. Назовите его DataWizardMDB.
В окне Solution Explorer щелкаем правой кнопкой мыши на имени проекта DataWizardMDB и в появившемся меню выбираем Add/Add New Item. В появившемся окне выбираем мастер Data Form Wizard, как показано на рис 2.1(рис 2.1) Создание Data Form Wizard
Называем новую форму DataFormMDB.cs. В появившемся мастере нажимаем кнопку "Next". В следующем шаге определяется объект DataSet, название которого должно соответствовать содержимому, поэтому называем его dsTourists. В следующем шаге мастера "Choose a data connection" требуется создать подключение к базе данных. Поскольку у нас еще нет никакого подключения, нажимаем на кнопку "New Connection". В появившемся окне "Свойства связи с данными" необходимо определить параметры создаваемого подключения. Переключаемся на вкладку "Поставщик данных" для выбора нужного поставщика OLE DB (рис. 2.2):
(рис 2.2) Определение поставщика данныхПоставщик данных Microsoft Jet 4.0 OLE DB Provider позволяет подключаться к базам данных формата Microsoft Aceess (mdb). Нажимаем кнопку "Далее" (или переходим на вкладку "Подключение") (рис. 2.3 ):
(рис 2.3) Задание параметров подключенияВ пункте 1 нажимаем кнопку (...) и указываем путь к базе данных BDTur_firm.mdb, расположенную на вашем компьютере. В пункте 2 можно оставить значение по умолчанию - если вы специально не изменяли имя пользователя и пароль доступа к базе, то стандартное имя "Admin" позволит создать подключение. Если вы правильно настроили права доступа к базе данных, то при нажатии кнопки "Проверить подключение" система выдаст сообщение "Проверка подключения выполнена". На вкладках "Дополнительно" и "Все" можно устанавливать права доступа и просматривать все свойства формируемого подключения. Не изменяя ничего на этих вкладках, нажимаем "OK".
Далее нам предстоит определить, какую таблицу базы данных мы собираемся извлекать. В окне мастера перечислены все доступные в схеме базы данных таблицы, представления и хранимые процедуры. Выберите в списке Available Items нужные таблицы и переместите их в список Selected Items, щелкнув кнопку с направленной вправо стрелкой. Если вы ошиблись и хотите удалить какие-то таблицы из списка Selected Items, выберите их и щелкните кнопку со стрелкой влево. Кроме того, добавлять и удалять таблицы можно, дважды щелкнув их название мышью. Выбираем две таблицы: "Туристы" и "Информация о туристах" (рис. 2.4):

Теперь необходимо определить отношение между таблицами. Отношения позволяют обеспечивать соблюдение правил ссылочной целостности, каскадно передавая изменения от одной таблицы к другой. Кроме того, они упрощают поиск данных в таблицах. Название отношения рекомендуется составлять из имен родительской и
Далее определяем столбцы (поля), извлекаемые из обеих таблиц. Оставляем все поля (рис. 2.5).
В последнем шаге мастера предстоит определить вид размещения данных на форме - всех записей в виде таблицы ( All records in a grid ) либо каждой записи в отдельном текстовом поле ( Single records in ). Выбираем второй вариант. Здесь же можно определить наличие дополнительных элементов управления - кнопок навигации и изменения записей. Оставляем эти значения по умолчанию. Завершаем работу мастера, нажимая кнопку "Finish".
Возникает сообщение - "Пароль будет сохранен в виде текста и будет доступен для чтения в коде и сборке". Выбрав "Include password", вы включаете пароль в приложение (он будет доступен), но избавляетесь от необходимости введения имени пользователя и пароля каждый раз при подключении к базе данных (рис. 2.6).
(рис 2.6) Выбор расположения пароляПрактически все готово. Однако, запустив приложение, мы обнаруживаем, что по-прежнему появляется пустая форма Form1. Переходим в код Form1 и копируем следующий участок кода:
[STAThread]
static void Main()
{
Application.Run(new Form1());
}
В коде DataFormMDB после Windows вставляем код и изменяем название запускаемой формы:
static void Main()
{
Application.Run(new DataFormMDB ());
}
В окне Solution Explorer щелкаем правой кнопкой на Form1.cs и удаляем его. Теперь, запуская приложение, мы видим DataFormMDB (рис. 2.7):
(рис 2.7) Готовая формаВ созданном приложении имеется несколько кнопок. Для загрузки данных нажимаем кнопку Load. Для перемещения по записям используем навигационные кнопки. При этом во второй таблице отображается список туристов. Для добавления новой или удаления текущей записи служат кнопки Add и Delete, для
Подключение к базе данных с помощью мастера позволяет создать приложение без всякого знания технологии ADO .NET. Конечно же, подобная разработка не может нас устраивать для коммерческих приложений, требующих несравненно более гибкого кода. DataForm Wizard всего лишь генерирует код, который можно просматривать и изменять в соответствии с задачами проекта.
В программном обеспечении к курсу вы найдете приложение DataWizardMDB (Code\Glava1 DataWizardMDB).
Модель объектов ADO .NET состоит из набора классов. DataSet представляет собой класс ADO .NET, который отвечает за отображение таблицы (или таблиц, или даже всей базы) используемой базы данных, на компьютере пользователя без непрерывной связи с базой данных. В приложении, созданном с помощью Data Form Wizard, мы имели возможность вносить изменения в загруженную таблицу, перемещаться по записям, причем до нажатия кнопки Update изменения в самой базе данных, т.е. в файле RBProduct.mdb, не происходило. В чем же дело? Дело в том, что все данные и были загружены в объект DataSet, созданный мастером. Только при нажатии кнопки Update происходила передача данных из DataSet в саму базу данных. Не следует путать объект DataSet c оперативной памятью компьютера - загруженная таблица не находится в оперативной памяти компьютера.
Представьте себе, что вы обслуживаете гипотетическую доску объявлений. Каждое утро вы берете обычный бумажный блокнот, записываете в него все свежие объявления, хранящиеся в централизованном банке данных, и отправляетесь к доске. Вы переписываете из блокнота на доску все объявления, а в блокнот записываете все те объявления, которые были добавлены на доску посетителями. Затем вы возвращаетесь в DataSet. В этом процессе самым важным - для вас, конечно, не для централизованного банка данных, - будет ваш блокнот. Аналогично, класс DataSet является ключевым во всей модели классов ADO .NET.
DataSet состоит из объектов типа DataTable и объектов DataRelation. В коде к ним можно обращаться как к свойствам объекта DataSet, т.е., используя Tables возвращает объект типа DataTableCollection, который содержит все объекты DataTable используемой базы данных.
Объекты DataTable используются для представления таблиц в DataSet. DataTable представляет одну таблицу из базы данных. В свою очередь, DataTable составляется из объектов DataColumn.
DataColumn - это блок для создания схемы DataTable. Каждый объект DataColumn имеет свойство DataType, которое определяет тип данных, содержащихся в каждом объекте DataColumn. Например, вы можете ограничить тип данных до целых, строковых и десятичных чисел. Поскольку данные, содержащиеся в DataTable, обычно переносятся обратно в исходный источник данных, вы должны согласовывать тип данных с источником.
Объект DataSet имеет также свойство Relations, возвращающее коллекцию DataRelationCollection, которая в свою очередь состоит из объектов DataRelation. Каждый объект DataRelation выражает отношение между двумя таблицами (сами таблицы связаны по какому-либо полю (столбцу). Следовательно, эта связь осуществляется через объект DataColumn ).
Коллекция Rows объекта DataTable возвращает набор строк (записей) заданной таблицы. Эта коллекция используется для изучения результатов запроса к базе данных. Мы можем обращаться к записям таблицы как к элементам простого массива.
DataSet - это специализированный объект, содержащий образ базы данных. Для осуществления взаимодействия между DataSet и источником данных используется объект типа DataAdapter. Само название этого объекта - адаптер, преобразователь, - указывает на его природу. DataAdapter содержит метод Fill() для обновления данных из базы и заполнения DataSet.
Объект DBConnection осуществляет связь с источником данных. Эта связь может быть одновременно использована несколькими командными объектами. Объект DBCommand позволяет послать базе данных команду (как правило, команду SQL или хранимую процедуру). Объекты DBConnection и DBCommand иногда создаются неявно в момент создания объекта DataSet, но их также можно создавать явным образом.
Когда мы перетаскиваем на форму элемент управления, Visual Studio .NET автоматически генерирует код, описывающий этот элемент. Если при размещении кнопок, текстовых полей и других элементов управления создавать их программно нецелесообразно, то при работе с элементами данных все как раз наоборот - лучше всего создавать все объекты ADO .NET вручную, что обеспечивает большую гибкость приложения. Тем не менее на первых порах использования ADO .NET полезно работать с визуальной средой разработки.
Рассмотрим работу с базой данных Microsoft Acсess
| Microsoft Access, база данных xtreme | Microsoft SQL, база данных NorthwindCS |
Запустите Visual Studio .NET, создайте новый проект, тип проекта - Windows Application.
| Назовите его VisualDataMDB | Назовите его VisualDataSQL |
Размещаем на создавшейся форме элемент управления (рис 2.8) На вкладке Data находятся все элементы управления для работы с ADO.NET
Поместите на форму объект OleDbDataAdapter |
Поместите на форму объект SqlDataAdapter |
Перед нами появляется мастер настройки элемента управления. Для (рис 2.9) Поставщик данных Microsoft OLE DB Provider for SQL Server
Нажимаем кнопку "Далее" (или переходим на вкладку "Подключение") (рис. 2.10).
(рис 2.10) Определение параметров подключенияДля подключения к базе данных SQL, расположенной на вашем компьютере, в пункте 1 вводим ( local ) или просто точку - ".". В пункте 2 используем учетные сведения системы: по умолчанию пароль учетной записи администратора SQL Server - пустой. В пункте 3 выбираем базу данных NorthwindCS.
В следующем шаге мастера - определение типа запроса. Параметры, предлагаемые мастером, будут отличаться (рис. 2.11 и рис. 2.12):

(рис 2.12) Определение типа запросов объекта OleDbDataAdapter(рис 2.11) Определение типа запросов объекта SqlDbDataAdapterДля базы данных Microsoft Access мы можем только использовать SQL-запросы - другие значения не активны. Для базы данных Microsoft SQL Server мы можем либо применять SQL-запросы, либо создать новую хранимую процедуру ( stored procedure ), либо использовать существующую хранимую процедуру. Различия подобного рода определяются типом баз данных. Для объекта SqlDataAdapter оставляем значение, предложенное по умолчанию: использование SQL-запросов.
В следующем шаге - создание SQL-запросов (Generate OleDbDataAdapter:
(рис 2.13) Добавление таблицы в окно Построителя запросов Выбираем таблицу Customer ( Customers ), нажимаем кнопку Add и затем Close. Затем в окне Query Builder выбираем все столбцы (All Columns), как показано на рис. 2.14:
(рис 2.14) Добавление столбцов. Поставив галочку напротив пункта (All Columns), мы извлекаем все столбцы из таблицыНажимаем кнопку OK. В окне "Generate the
SELECT
Customer.*
FROM
Customer
|
SELECT
Customers.*
FROM
Customers
|
Обратите внимание, что синтаксис этого запроса несущественно отличается от "классического" SQL- запроса, рассмотренного выше.
Нажимаем кнопку Next. В окне "Обзор результатов мастера" (View Wizard Results) приводится список результатов работы мастера. Вид этого списка может отличаться, как это изображено на рис. 2.15 и 2.16:

(рис 2.16) Список результатов работы мастера объекта OleDbDataAdapter(рис 2.15) Список результатов работы мастера объекта SqlDbDataAdapterЧем обусловлено это различие? Для базы данных Access мастером создана возможность не только просмотра данных из базы данных - SQL-запрос SELECT, но и возможность ее изменения - запросы INSERT, UPDATE, DELETE. Для базы данных SQL Server создана лишь возможность просмотра базы данных. Для изменения данных необходимо проходить авторизацию (см. рис. 2.10) с учетной записью администратора базы данных.
Нажимаем кнопку Finish. Для объекта OleDbDataAdapter возникает окно (см. рис. 2.6), которое мы уже описывали выше.
Мастер создал на панели компонент по два элемента: oleDbDataAdapter1 и oleDbConnection1 для VisualDataMDB и sqlDbDataAdapter1 и sqlDbConnection1 для VisualDataSQL. oleDbDataAdapter1 (или sqlDbDataAdapter1 ) является основным компонентом типа OleDbData Adapter (или SqlDataAdapter ), который мы создавали при помощи мастера. Объект oleDbConnection1 (или sqlDbConnection1 ) был создан мастером как необходимый элемент подключения к базе. Образно говоря, мы получили адаптер ( DataAdapter1 ) и вилку ( Connection1 ) для подключения к источнику данных. Теперь нам необходимо добавить объект DataSet - тот самый "буфер", в котором будет храниться информация, полученная из базы данных. Щелкаем на oleDbDataAdapter1 (или sqlDbDataAdapter1 ), для его выделения. Открываем свойства этого элемента. На информационной панели щелкаем на ссылку "Generate DataSet" для создания объекта
(рис 2.17) Создание DataSetВ появившемся окне "Generate DataSet" задаем имена - dsCustomer и dsCustomers соответственно.
Итак, все "невидимые" части механизма подключения к базе данных у нас уже есть. Осталось теперь связать видимый интерфейс с данными. Объектом, отображающим данные на форме, у нас является dataGrid1. В свойстве этого элемента DataSource (источник данных) выбираем в качестве источника созданный объект dsCustomer1 (рис. 2.18).
(рис 2.18) Определение источника данных для элемента управления dataGrid1На форме в режиме дизайна у нас немедленно появилась символическая таблица со знаком (+). Последнее, что нам осталось сделать, - это заполнить объект DataSet (здесь - dsCustomer1 ). Переходим в код форм и вносим соответствующие добавления:
using System.Data.OleDb;
// Подключаем пространство имен для работы с поставщиком OleDb
private void Form1_Load(object sender, System.EventArgs e)
{
oleDbDataAdapter1.Fill(dsCustomer1);
}
using System.Data.SqlClient;
// Подключаем пространство имен для работы с поставщиком SQL
private void Form1_Load(object sender, System.EventArgs e)
{
sqlDataAdapter1.Fill(dsCustomers1);
}
В обоих случаях в методе загрузки формы вызываем метод Fill объекта oleDbDataAdapter1 (или sqlDbDataAdapter1 ) и передаем ему в качестве параметра dsCustomer1. Опять же, говоря образно, мы "заливаем" данные из адаптера в DataSet, который затем распоряжается ими - здесь мы определили, что DataSet выступает в качестве источника данных для dataGrid1.
Запустите приложения. Щелкните на знак (+), а затем на ссылку "Customer". Готовые приложения будут иметь следующий вид (рис. 2.19 и 2.20):

(рис 2.20) Готовое приложение VisualDataMDB(рис 2.19) Готовое приложение VisualDataSQLВ программном обеспечении к курсу вы найдете эти
В состав Visual Studio .NET входит замечательный инструмент управления и обзора подключениями к базам данных -
(рис 2.21) Добавление соединения Появляется окно мастера "Свойства связи с данными", с которым мы уже встречались (см. рис. 2.2 и 2.3). Создайте самостоятельно подключение к базе данных xtreme - после того как вы это сделаете, оно появится в списке всех подключений окна
(рис 2.22) В окне Server Explorer выводятся все созданные подключения к базам данныхЩелкните на знак (+) около названия подключения, откройте Tables, выберите таблицу Customer и перетащите ее на форму (рис. 2.23).
(рис 2.23) Содержимое базы данных xtremeПри появлении уже знакомого окна расположения пароля (см. рис. 2.6) выбираем "Include Password".
На панели компонент формы появились два элемента: oleDb Connection1 и oleDbDataAdapter1. Выделяем щелчком oleDbDataAdapter1, открываем его свойства, на информационной панели нажимаем "Generate DataSet". Называем объект "DataSet dsCustomer" и нажимаем "ОК". Помещаем на форме элемент управления DataGrid, в свойствах этого элемента указываем расположение Dock - Fill, DataSource - dsCustomer и переходим в код формы. Добавляем уже знакомый нам код:
private void Form1_Load(object sender, System.EventArgs e)
{
oleDbDataAdapter1.Fill(dsCustomer1);
}
Запускаем приложение. Его внешний вид ничем не отличается от приложения, рассмотренного в предыдущем примере.
Созданное подключение к базе данных xtreme теперь будет отображаться во всех последующих проектах в окне
Вы также можете использовать окно Solution Explorer для быстрого просмотра содержимого баз данных и - если подключение было создано с правами администратора - изменения их. Откройте нужную таблицу и просто дважды щелкните на нее (рис. 2.24):
(рис 2.24) Просмотр таблицы Customers базы данных NorthwindCS
Мы рассмотрели создание приложений для работы с базами данных с использованием различных мастеров. Однако разрабатывать такие приложения можно также без использования визуальной среды. Создадим такие же приложения, как и в предыдущем примере.
Будет работать с теми же самыми таблицами.
| Microsoft Access, база данных xtreme Таблица Customer | Microsoft SQL, база данных NorthwindCS Таблица Customers. |
Запустите Visual Studio .NET, создайте новый проект, тип проекта - Windows Application.
| Назовите его ProgrammDataMDB | Назовите его ProgrammDataSQL |
Размещаем на создавшейся форме элемент управления DataGrid, свойству Dock устанавливаем значение "Fill". Переходим в код формы. Подключаем соответствующие пространства имен:
using System.Data.OleDb; |
using System.Data.SqlClient; |
В конструкторе формы после InitializeComponent создаем объект DataAdapter:
public Form1()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();
OleDbDataAdapter dataAdapter =
new OleDbDataAdapter(CommandText, ConnectionString);
}
public Form1()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();
SqlDataAdapter dataAdapter =
new SqlDataAdapter(CommandText, ConnectionString);
}
В качестве параметров DataAdapter мы передаем CommandText и ConnectionString. Переменная типа string CommandText представляет собой обычный SQL-запрос на выборку из таблицы Customer, а переменная типа СonnectionString - это так называемая строка подключения, в которой указываются расположение базы данных, ее название, параметры авторизации и проч. Далее мы рассмотрим более подробно эти строки. Как составить эти переменные? Можно, конечно, написать вручную, но мы сейчас воспользуемся строчками, сгенерированными мастером. Откройте предыдущие проекты - VisualDataMDB и VisualDataSQL. Перейдите в код формы. Раскройте область Windows
Для CommandText:
this.oleDbSelectCommand1.CommandText = @"SELECT Address1, Address2, City, [Contact First Name], [Contact Last Name], [Contact Position], [Contact Title], Country, [Customer Credit ID], [Customer ID], [Customer Name], [E-mail], Fax, [Last Year's Sales], Phone, [Postal Code], Region, [Web Site] FROM Customer";
this.sqlSelectCommand1.CommandText = "SELECT CustomerID, CompanyName, ContactName, ContactTitle, Address, City, Region, PostalCode, Country, Phone, Fax FROM Customers";
Для
this.oleDbConnection1.ConnectionString = @" Jet OLEDB:Global Partial Bulk Ops=2;Jet OLEDB:Registry Path=; Jet OLEDB:Database Locking Mode=1; Jet OLEDB:Database Password=;Data Source=""E:\Program Files\Microsoft Visual Studio .NET 2003\Crystal Reports\Samples\Database\xtreme.mdb" ";Password=;Jet OLEDB:Engine Type=5;Jet OLEDB:Global Bulk Transactions=1;Provider=""Microsoft.Jet.OLEDB.4.0"";Jet OLEDB:System database=;Jet OLEDB:SFP=False;Extended Properties=; Mode=Share Deny None;Jet OLEDB:New Database Password=;Jet OLEDB:Create System Database=False;Jet OLEDB:Don'Jet Copy Locale on Compact=False;Jet OLEDB:Compact Without Replica Repair=False;User ID=Admin;Jet OLEDB:Encrypt Database=False";
this.sqlConnection1.ConnectionString = "workstation id=7EA2B2F6068D473;packet size=4096;integrated security=SSPI; data source=\"(local) \";persist security info=False; initial catalog=NorthwindCS";
Скопируйте эти строчки, начиная от названия самих переменных, затем в коде форм ProgrammDataMDB и ProgrammDataSQL в классе Form 1 объявите две переменные по две переменных типа string и вставьте скопированные значения:
string CommandText = @"SELECT Address1, Address2, City, [Contact First Name], [Contact Last Name], [Contact Position], [Contact Title], Country, [Customer Credit ID], [Customer ID], [Customer Name], [E-mail], Fax, [Last Year's Sales], Phone, [Postal Code], Region, [Web Site] FROM Customer";
string ConnectionString = @"Jet OLEDB:Global Partial Bulk Ops=2;Jet OLEDB:Registry Path=;Jet OLEDB:Database Locking Mode=1; Jet OLEDB:Database Password=;Data Source=""E:\Program Files\Microsoft Visual Studio .NET 2003\Crystal Reports\Samples\Database\xtreme.mdb"";Password=; Jet OLEDB:Engine Type=5;Jet OLEDB:Global Bulk Transactions=1;Provider=""Microsoft.Jet.OLEDB.4.0""; Jet OLEDB:System database=;Jet OLEDB:SFP=False;Extended Properties=; Mode=Share Deny None;Jet OLEDB:New Database Password=; Jet OLEDB:Create System Database=False;Jet OLEDB:Don' Jet Copy Locale on Compact=False;Jet OLEDB:Compact Without Replica Repair=False; User ID=Admin;Jet OLEDB:Encrypt Database=False";
string CommandText = "SELECT CustomerID, CompanyName, ContactName, ContactTitle, Address, City, Region, PostalCode, Country, Phone, Fax FROM Customers";
string ConnectionString = "workstation id=7EA2B2F6068D473;packet size=4096;integrated security=SSPI;data sou" + "rce=\"(local)\";persist security info=False;initial catalog=NorthwindCS";
Обратите внимание на названия переменных CommandText и ConnectionString. Когда мы создаем объект DataAdapter, в качестве параметров мы можем передать названия строк, таких как cmdText и conString, или даже и cns - совершенно равноправно, не забыв, конечно же, назвать также эти переменные в классе Form1. Но сама среда Visual Studio .NET генерирует эти строки именно с такими названиями - CommandText и ConnectionString, поэтому если вы пишите их не вручную, то облегчаете работу, называя их так же, как и среда.
Возвращаемся к нашим приложениям - ProgrammDataMDB и ProgrammDataSQL. Дальнейший код будет совершенно одинаковым для обоих приложений.
Итак, создаем объект DataSet:
DataSet ds = new DataSet();
Заполняем таблицу Customer объекта ds данными из базы:
dataAdapter.Fill(ds, "Customer");
Cвязываем источник данных объекта dataGrid1 (который мы нанесли на форму в режиме дизайна) с таблицей Customer объекта ds:
dataGrid1.DataSource = ds.Tables["Customer"].DefaultView;
Все! Запускаем оба приложения. Если вы были внимательны в самом начале, то заметили, что в базе данных xtreme таблица называется Customer, а в базе данных NorthwindCS - Customers ( "s" на конце). Тем не менее код работает для обоих приложений. В чем же дело? Таблица, которую мы называем "Customer", при вызове метода Fill объекта dataAdapter может быть названа как угодно - ее содержимое будет представлять собой извлекаемую таблицу из базы данных. При указании источника данных ( DataSource ) для объекта dataGrid1 мы ссылаемся именно на таблицу Customer, которая была создана при вызове метода Fill. Точнее говоря, эта таблица определена в объекте DataSet, а именно к нему мы и обращаемся для заполнения данными нашей формы в соответствии с моделью ADO .NET. Чтобы убедиться в этом, попробуйте такой код:
DataSet ds = new DataSet(); dataAdapter.Fill(ds, "Bezimyannaya"); dataGrid1.DataSource = ds.Tables["Bezimyannaya"].DefaultView;
По-прежнему все работает. Означает ли это, что можно небрежно относиться к названию таблицы в DataSet? Нет - в нашем учебном примере мы с самого начала извлекали только одну таблицу из базы данных. В реальных приложениях приходится иметь дело с десятками таблиц, и будет возникать большая путаница, если называть таблицы как попало. Поэтому следует давать названия таблицам в объекте DataSet названия тех таблиц, образы которых они представляют.
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Data.OleDb;
namespace ProgrammDataMDB
{
/// <summary>
/// Summary description for Form1.
/// </summary>
public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.DataGrid dataGrid1;
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;
string CommandText = @"SELECT Address1, Address2, City,
[Contact First Name], [Contact Last Name], [Contact Position],
[Contact Title], Country, [Customer Credit ID], [Customer ID],
[Customer Name], [E-mail], Fax, [Last Year's Sales],
Phone, [Postal Code], Region, [Web Site] FROM Customer";
string ConnectionString = @"Jet OLEDB:Global Partial Bulk Ops=2;Jet
OLEDB:Registry Path=;Jet OLEDB:Database Locking Mode=1;Jet
OLEDB:Database Password=;Data Source=""E:\Program
Files\Microsoft Visual Studio .NET 2003\Crystal
Reports\Samples\Database\xtreme.mdb"";Password=;Jet
OLEDB:Engine Type=5;Jet OLEDB:Global Bulk
Transactions=1;Provider=""Microsoft.Jet.OLEDB.4.0"";
Jet OLEDB:System database=;Jet OLEDB:SFP=False;Extended
Properties=;Mode=Share Deny None;Jet OLEDB:New Database Password=;
Jet OLEDB:Create System Database=False;Jet OLEDB:Don'
Jet Copy Locale on Compact=False;Jet OLEDB:Compact Without
Replica Repair=False;User ID=Admin;
Jet OLEDB:Encrypt Database=False";
public Form1()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();
OleDbDataAdapter dataAdapter =
new OleDbDataAdapter(CommandText, ConnectionString);
DataSet ds = new DataSet();
dataAdapter.Fill(ds, "Bezimyannaya");
dataGrid1.DataSource = ds.Tables["Bezimyannaya"].DefaultView;
//
// TODO: Add any constructor code after InitializeComponent call
//
}
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
Windows Form Designer generated code
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.Run(new Form1());
}
private void Form1_Load(object sender, System.EventArgs e)
{
}
}
}
Полный листинг программы - подключение к базе данных NorthwindCS:
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Data.SqlClient;
namespace ProgrammDataSQL
{
/// <summary>
/// Summary description for Form1.
/// </summary>
public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.DataGrid dataGrid1;
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;
string CommandText = "SELECT CustomerID, CompanyName,
ContactName, ContactTitle, Address, City, Region," +
" PostalCode, Country, Phone, Fax FROM Customers";
string ConnectionString = "workstation id=7EA2B2F6068D473;packet
size=4096;integrated security=SSPI;data sou" +
"rce=\"(local)\";persist security info=False;initial
catalog=NorthwindCS";
public Form1()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();
SqlDataAdapter dataAdapter =
new SqlDataAdapter(CommandText, ConnectionString);
DataSet ds = new DataSet();
dataAdapter.Fill(ds, "Customer");
dataGrid1.DataSource = ds.Tables["Customer"].DefaultView;
//
// TODO: Add any constructor code after InitializeComponent call
//
}
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
Windows Form Designer generated code
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.Run(new Form1());
}
private void Form1_Load(object sender, System.EventArgs e)
{
}
}
}
Для извлечения таблиц и содержащихся в них данных используются SQL-запросы. Переменная CommandText содержит в себе SQL-запрос, синтаксис которого адаптирован для данного поставщика данных. Мы можем управлять извлечением данных, изменяя строку CommandText. Скопируйте папку проекта ProgrammDataSQL и назовите ее CommandText. Запустите проект и перейдите в код формы. Изменим string СommandText так, чтобы извлекать в DataGrid только поля CustomerID, ContactName, Country и Phone. Для этого удалим ненужные поля, в результате получится следующий SQL-запрос:
string CommandText = "SELECT CustomerID, ContactName, Country, Phone FROM Customers";
Запустите приложение. Теперь на форму выводятся только соответствующие четыре поля (рис. 2.25):
(рис 2.25) Ограничение выводимых полей Выведем теперь все записи клиентов, имена которых начинаются на "М":
string CommandText = "SELECT CustomerID, ContactName, Country, Phone FROM Customers where ContactName like 'M%'";
Запускаем приложение. Запрос выбрал только записи на букву "M" (рис. 2.26).
(рис 2.26) Ограничение выводимых полейВы можете использовать все возможности языка SQL для отбора данных и модификации строки CommandText для получения нужного результата. Не пробуйте только использовать команды insert, update или delete - изменение записей в базе данных мы рассмотрим позже.
В программном обеспечении к курсу вы найдете приложение СommandText (Code\Glava1\ СommandText).
Строка соединения ConnectionString определяет параметры, необходимые для установления соединения с источником данных. Строка соединений при использовании мастеров генерируется средой, но можно (и желательно - во избежание неточностей и ошибок) писать эту строчку вручную. Рассмотрим еще раз строки соединения, которые были созданы при подключении к базам данных xtreme и Northwind.
База данных xtreme, проект ProgrammDataMDB:
string ConnectionString = @"Jet OLEDB:Global Partial Bulk Ops=2; Jet OLEDB:Registry Path=;Jet OLEDB:Database Locking Mode=1; Jet OLEDB:Database Password=;Data Source=" "E:\Program Files\Microsoft Visual Studio .NET 2003\Crystal Reports\Samples\Database\xtreme.mdb"";Password=; Jet OLEDB:Engine Type=5;Jet OLEDB:Global Bulk Transactions=1;Provider=""Microsoft.Jet.OLEDB.4.0""; Jet OLEDB:System database=;Jet OLEDB:SFP=False;Extended Properties=; Mode=Share Deny None;Jet OLEDB:New Database Password=; Jet OLEDB:Create System Database=False;Jet OLEDB:Don' Jet Copy Locale on Compact=False; Jet OLEDB:Compact Without Replica Repair=False;User ID=Admin; Jet OLEDB:Encrypt Database=False";
База данных NorthwindCS, проект ProgrammDataSQL:
string ConnectionString = "workstation id=7EA2B2F6068D473;packet size=4096; integrated security=SSPI;data sou" + "rce=\"(local)\";persist security info=False; initial catalog=NorthwindCS";
В этих строках через точку с запятой просто перечисляются параметры соединения. В таблице 2.1 приводятся основные значения этих параметров.
| Параметр | Описание |
|---|---|
Provider (Поставщик) |
Свойство применяется для установки или возврата имени поставщика для соединения, используется только для объектов OleDbConnection |
Connection Timeout или Connect Timeout (Время ожидания связи) |
Длительность времени ожидания связи с сервером перед завершением попытки и генерацией исключения в секундах. По умолчанию 15 |
Initial Catalog (Исходный каталог) |
Имя базы данных |
Data Source (Источник данных) |
Имя используемого SQL-сервера, когда установлено соединение, или имя файла базы данных Microsoft Access |
Password (Пароль) |
Пользовательский пароль для учетной записи SQL Server |
User ID (Пользовательский ID) |
Пользовательское имя для учетной записи SQL Server |
Workstation ID |
Имя рабочей станции или компьютера |
Integrated Security или Trusted Connection (Интегрированная безопасность или Доверительное соединение) |
Параметр, который определяет, является ли соединение защищенным. True, False и SSPI - возможные значения. (SSPI - эквивалент True) |
Persist Security Info (Удержание защитной информации |
Когда установлено False, нуждающаяся в защите информация, такая как пароль, не возвращается как часть соединения, если связь установлена или когда-либо была установленной. Выставление этого свойства в True может быть рискованным в плане безопасности. По умолчанию False |
При создании мастером строки ConnectionString происходит генерирование большого количества лишних параметров. Нельзя сказать, что они не нужны, просто мастер предусматривает все возможности использования этого подключения и вставляет соответствующие значения. В действительности необходимых значений для простого извлечения данных всего несколько:
Скопируйте папки с проектами ProgrammDataMDB и Programm DataSQL. Переименуйте копии в ConnStringMDB и ConnStringSQL. Измените значения ConnectionString следующим образом:
База данных xtreme, проект ConnStringMDB:
string ConnectionString = @"Provider=""Microsoft.Jet.OLEDB.4.0""; Data Source=""E:\Program Files\Microsoft Visual Studio .NET 2003\Crystal Reports\Samples\Database\xtreme.mdb""; User ID=Admin;Jet OLEDB:Encrypt Database=False";
База данных NorthwindCS, проект ConnStringSQL:
string ConnectionString = "workstation id=7EA2B2F6068D473;integrated security=SSPI; data source=\"(local)\";persist security info=False; initial catalog=NorthwindCS";
Мы значительно сократили количество параметров, получив прежнюю функциональность приложений.
Где определяется строка подключения, когда мы создаем объект DataAdapter не программно, а с помощью мастера? Среда генерирует строку подключения вместе с кодом для DataAdapter, и в этом нетрудно убедиться. Запустите приложение, которое мы делали, вообще ничего не зная об объектах ADO .NET - DataWizardMDB. Перейдите в код формы, откройте область Windows
this.oleDbConnection1.ConnectionString = @"Jet OLEDB:Global Partial Bulk Ops=2; Jet OLEDB:Registry Path=;Jet OLEDB:Database Locking Mode=1; Jet OLEDB:Database Password=;Data Source=" "D:\Uchebnik\Code\Glava4\RBProduct.mdb" ";Password=;Jet OLEDB:Engine Type=5; Jet OLEDB:Global Bulk Transactions=1;Provider=" "Microsoft.Jet.OLEDB.4.0""; Jet OLEDB:System database=;Jet OLEDB:SFP=False;Extended Properties=; Mode=Share Deny None;Jet OLEDB:New Database Password=; Jet OLEDB:Create System Database=False;Jet OLEDB:Don' Jet Copy Locale on Compact=False; Jet OLEDB:Compact Without Replica Repair=False; User ID=Admin;Jet OLEDB:Encrypt Database=False";
Когда мы переносим объект DataAdapter из панели инструментов Toolbox (со вкладки Data) на форму, вместе с ним образуется объект DBConnection, в свойствах которого указывается строка ConnectionString и другие параметры подключения (рис. 2.27):
(рис 2.27) Свойства объекта sqlConnection1 проекта VisualDataSQL
Большинство источников данных поддерживает ограниченное количество соединений. Так, база данных Microsoft Access может поддерживать одновременную работу не более чем с 255 пользователями. При попытке обращения к базе данных, лимит соединений которой исчерпан, пользователь не получит нужной ему информации и будет вынужден ждать освобождения соединения. Задача разработчика заключается в минимизации времени связи с базой данных, поскольку соединение занимает полезные системные ресурсы.
Когда вы вызываете у объекта DataAdapter метод (например, Fill ), то он сам проверяет, открыто ли соединение. Если соединения нет, то DataAdapter открывает соединение, выполняет задачи и затем закрывает соединение.
Явное управление соединением - лучший подход к работе с базами данных. Он обладает рядом преимуществ:
Для явного управления соединением используется объект Connection. Создайте новый проект и назовите его ConnectionMDB. Перетащите элемент управления DataGrid из панели инструментов Toolbox и установите свойству Dock значение Fill. Перейдите в код формы. Подключаем пространство имен:
using System.Data.OleDb;
В конструкторе Form1 после InitializeComponent создаем объект Connection:
OleDbConnection conn = new OleDbConnection(ConnectionString);
В качестве параметра объекту conn передается строка подключения ConnectionString.
Можно также устанавливать строку подключения через свойство созданного объекта сonn:
OleDbConnection conn = new OleDbConnection(); conn.ConnectionString = ConnectionString;
Теперь нам необходимо определить параметры самой строки ConnectionString. Вы можете сделать это вручную или скопировав код из приложения ConnStringMDB (подключаться будем к базе данных xtreme).
string ConnectionString = @"Provider=""Microsoft.Jet.OLEDB.4.0""; Data Source=""E:\Program Files\Microsoft Visual Studio .NET 2003\Crystal Reports\Samples\Database\xtreme.mdb"";User ID=Admin;Jet OLEDB:Encrypt Database=False";
Теперь можно устанавливать соединение, вызывая метод Open объекта Connection:
OleDbConnection conn = new OleDbConnection(); conn.ConnectionString = ConnectionString; conn.Open();
Объект Command применяется для выполнения SQL-запросов к источнику данных. Чтобы выполнить запрос, свойству Connection объекта Command следует задать объект - имя созданного Connection:
OleDbConnection conn = new OleDbConnection(); conn.ConnectionString = ConnectionString; conn.Open(); OleDbCommand myCommand = new OleDbCommand(); myCommand.Connection = conn;
Объект Connection также предоставляет метод CreateCommand, позволяющий упростить данный процесс - этот метод возвращает новый объект Command, уже инициализированный для использования вашего объекта Connection:
OleDbConnection conn = new OleDbConnection(); conn.ConnectionString = ConnectionString; conn.Open(); OleDbCommand myCommand = conn.CreateCommand();
Эти два способа совершенно эквивалентны.
Теперь нам следует определить SQL-запрос, который будет извлекать данные. Как и раньше, строкой, в которой будет содержаться этот запрос, будет CommandText. Объявляем переменную CommandText, извлекающую все столбцы таблицы Customer:
string сommandText = @"SELECT Address1, Address2, City, [Contact First Name], [Contact Last Name], [Contact Position], [Contact Title], Country, [Customer Credit ID], [Customer ID], [Customer Name], [E-mail], Fax, [Last Year's Sales], Phone, [Postal Code], Region, [Web Site] FROM Customer";
Объект myСommand имеет свойство, которое так и называется - CommandText. Чтобы избежать путаницы, изменим название переменной - CommandText на commandText (с маленькой буквы):
myCommand.CommandText = commandText;
Создаем объект OleDbDataAdapter:
OleDbDataAdapter dataAdapter = new OleDbDataAdapter();
Объект dataAdapter имеет свойство SelectCommand в котором мы и будем указывать объект myCommand:
dataAdapter.SelectCommand = myCommand;
Создаем объект DataSet:
DataSet ds = new DataSet();
Заполняем ds данными из dataAdapter:
dataAdapter.Fill(ds, "Customers");
Указываем источник данных DataSource для dataGrid1:
dataGrid1.DataSource = ds.Tables["Customers"].DefaultView;
Закрываем соединение явным образом:
conn.Close();
Все! Запускаем приложение. Мы получили уже знакомый результат, но теперь мы действительно управляем всеми объектами, работающими с данными.
Полный листинг проекта ConnectionMDB:
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Data.OleDb;
namespace ConnectionMDB
{
/// <summary>
/// Summary description for Form1.
/// </summary>
public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.DataGrid dataGrid1;
string ConnectionString =
@"Provider=""Microsoft.Jet.OLEDB.4.0"";
Data Source=""E:\Program Files\Microsoft Visual Studio
.NET 2003\Crystal Reports\Samples\Database\xtreme.mdb"
";User ID=Admin;Jet OLEDB:Encrypt Database=False";
string commandText = @"SELECT Address1, Address2, City,
[Contact First Name], [Contact Last Name], [Contact Position],
[Contact Title], Country, [Customer Credit ID], [Customer ID],
[Customer Name], [E-mail], Fax, [Last Year's Sales],
Phone, [Postal Code], Region, [Web Site] FROM Customer";
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;
public Form1()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();
OleDbConnection conn = new OleDbConnection(ConnectionString);
//OleDbConnection conn = new OleDbConnection();
//conn.ConnectionString = ConnectionString;
conn.Open();
OleDbCommand myCommand = new OleDbCommand();
myCommand.Connection = conn;
myCommand.CommandText = commandText;
//OleDbCommand myCommand = conn.CreateCommand();
OleDbDataAdapter dataAdapter = new OleDbDataAdapter();
dataAdapter.SelectCommand = myCommand;
DataSet ds = new DataSet();
dataAdapter.Fill(ds, "Customers");
dataGrid1.DataSource = ds.Table
["Customers"].DefaultView;
conn.Close();
//
// TODO: Add any constructor code after InitializeComponent call
//
}
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
Windows Form Designer generated code
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.Run(new Form1());
}
private void Form1_Load(object sender, System.EventArgs e)
{
}
}
}
Сравните использование строк ConnectionString и connectingText объектом myCommand с аналогичным использованием объектом DataAdapter ( ProgrammDataMDB и ProgrammDataSQL ).
Создание объекта Connection для базы данных SQL принципиально не отличается от примера, рассмотренного выше. В следующем фрагменте кода описываются те же объекты Connection и Command:
using System.Data.SqlClient; string CommandText = "SELECT CustomerID, CompanyName, ContactName, ContactTitle, Address, City, Region, PostalCode, Country, Phone, Fax FROM Customers"; string connectionString = "workstation id=7EA2B2F6068D473; integrated security=SSPI;data source=\"(local)\"; persist security info=False;initial catalog=NorthwindCS"; SqlConnection conn = new SqlConnection(connectionString); //SqlConnection conn = new SqlConnection(); //conn.ConnectionString = ConnectionString; conn.Open(); SqlCommand myCommand = new SqlCommand(); myCommand.Connection = conn; myCommand.CommandText = CommandText; //SqlCommand myCommand = conn.CreateCommand(); SqlDataAdapter dataAdapter = new SqlDataAdapter(); dataAdapter.SelectCommand = myCommand; DataSet ds = new DataSet(); dataAdapter.Fill(ds, "Customers"); dataGrid1.DataSource = ds.Tables["Customers"].DefaultView; conn.Close();
В программном обеспечении к курсу вы найдете приложения ConnectionMDB и ConnectionSQL (Code\Glava1\ ConnectionMDB и ConnectionSQL).
У вас наверняка могло сложиться впечатление, что использование визуальных средств Microsoft Visual Studio .NET для добавления и конфигурирования объектов ADO .NET несравненно проще и логичней, чем программный способ создания этих объектов. Однако это впечатление глубоко ошибочно. В действительности только последний пример может претендовать на завершенное приложение - все остальные являются своего рода вспомогательными модулями. Повторю, что только полностью вручную написанный код объектов ADO .NET позволяет создавать ясные, надежные и гибкие приложения.
Мастер Data Form Wizard из Visual Studio .NET позволяет быстро, буквально в несколько шагов, создать связанную с данными форму. Код, генерируемый мастером, можно будет просматривать и изменять.
Мы рассмотрим подключение к базе данных Microsoft Access BDTur_firm.mdb, которую мы создали сами. Наша задача: вывести содержимое двух связанных таблиц - "Туристы" и "Информация о туристах" на Windows-форму.
Запустите Visual Studio .NET, создайте новый проект, тип проекта - Windows Application. Назовите его DataWizardMDB.
В окне Solution Explorer щелкаем правой кнопкой мыши на имени проекта DataWizardMDB и в появившемся меню выбираем Add/Add New Item. В появившемся окне выбираем мастер Data Form Wizard, как показано на рис 2.1(рис 2.1) Создание Data Form Wizard
Называем новую форму DataFormMDB.cs. В появившемся мастере нажимаем кнопку "Next". В следующем шаге определяется объект DataSet, название которого должно соответствовать содержимому, поэтому называем его dsTourists. В следующем шаге мастера "Choose a data connection" требуется создать подключение к базе данных. Поскольку у нас еще нет никакого подключения, нажимаем на кнопку "New Connection". В появившемся окне "Свойства связи с данными" необходимо определить параметры создаваемого подключения. Переключаемся на вкладку "Поставщик данных" для выбора нужного поставщика OLE DB (рис. 2.2):
(рис 2.2) Определение поставщика данныхПоставщик данных Microsoft Jet 4.0 OLE DB Provider позволяет подключаться к базам данных формата Microsoft Aceess (mdb). Нажимаем кнопку "Далее" (или переходим на вкладку "Подключение") (рис. 2.3 ):
(рис 2.3) Задание параметров подключенияВ пункте 1 нажимаем кнопку (...) и указываем путь к базе данных BDTur_firm.mdb, расположенную на вашем компьютере. В пункте 2 можно оставить значение по умолчанию - если вы специально не изменяли имя пользователя и пароль доступа к базе, то стандартное имя "Admin" позволит создать подключение. Если вы правильно настроили права доступа к базе данных, то при нажатии кнопки "Проверить подключение" система выдаст сообщение "Проверка подключения выполнена". На вкладках "Дополнительно" и "Все" можно устанавливать права доступа и просматривать все свойства формируемого подключения. Не изменяя ничего на этих вкладках, нажимаем "OK".
Далее нам предстоит определить, какую таблицу базы данных мы собираемся извлекать. В окне мастера перечислены все доступные в схеме базы данных таблицы, представления и хранимые процедуры. Выберите в списке Available Items нужные таблицы и переместите их в список Selected Items, щелкнув кнопку с направленной вправо стрелкой. Если вы ошиблись и хотите удалить какие-то таблицы из списка Selected Items, выберите их и щелкните кнопку со стрелкой влево. Кроме того, добавлять и удалять таблицы можно, дважды щелкнув их название мышью. Выбираем две таблицы: "Туристы" и "Информация о туристах" (рис. 2.4):

Теперь необходимо определить отношение между таблицами. Отношения позволяют обеспечивать соблюдение правил ссылочной целостности, каскадно передавая изменения от одной таблицы к другой. Кроме того, они упрощают поиск данных в таблицах. Название отношения рекомендуется составлять из имен родительской и
Далее определяем столбцы (поля), извлекаемые из обеих таблиц. Оставляем все поля (рис. 2.5).
В последнем шаге мастера предстоит определить вид размещения данных на форме - всех записей в виде таблицы ( All records in a grid ) либо каждой записи в отдельном текстовом поле ( Single records in ). Выбираем второй вариант. Здесь же можно определить наличие дополнительных элементов управления - кнопок навигации и изменения записей. Оставляем эти значения по умолчанию. Завершаем работу мастера, нажимая кнопку "Finish".
Возникает сообщение - "Пароль будет сохранен в виде текста и будет доступен для чтения в коде и сборке". Выбрав "Include password", вы включаете пароль в приложение (он будет доступен), но избавляетесь от необходимости введения имени пользователя и пароля каждый раз при подключении к базе данных (рис. 2.6).
(рис 2.6) Выбор расположения пароляПрактически все готово. Однако, запустив приложение, мы обнаруживаем, что по-прежнему появляется пустая форма Form1. Переходим в код Form1 и копируем следующий участок кода:
[STAThread]
static void Main()
{
Application.Run(new Form1());
}
В коде DataFormMDB после Windows вставляем код и изменяем название запускаемой формы:
static void Main()
{
Application.Run(new DataFormMDB ());
}
В окне Solution Explorer щелкаем правой кнопкой на Form1.cs и удаляем его. Теперь, запуская приложение, мы видим DataFormMDB (рис. 2.7):
(рис 2.7) Готовая формаВ созданном приложении имеется несколько кнопок. Для загрузки данных нажимаем кнопку Load. Для перемещения по записям используем навигационные кнопки. При этом во второй таблице отображается список туристов. Для добавления новой или удаления текущей записи служат кнопки Add и Delete, для
Подключение к базе данных с помощью мастера позволяет создать приложение без всякого знания технологии ADO .NET. Конечно же, подобная разработка не может нас устраивать для коммерческих приложений, требующих несравненно более гибкого кода. DataForm Wizard всего лишь генерирует код, который можно просматривать и изменять в соответствии с задачами проекта.
В программном обеспечении к курсу вы найдете приложение DataWizardMDB (Code\Glava1 DataWizardMDB).
Модель объектов ADO .NET состоит из набора классов. DataSet представляет собой класс ADO .NET, который отвечает за отображение таблицы (или таблиц, или даже всей базы) используемой базы данных, на компьютере пользователя без непрерывной связи с базой данных. В приложении, созданном с помощью Data Form Wizard, мы имели возможность вносить изменения в загруженную таблицу, перемещаться по записям, причем до нажатия кнопки Update изменения в самой базе данных, т.е. в файле RBProduct.mdb, не происходило. В чем же дело? Дело в том, что все данные и были загружены в объект DataSet, созданный мастером. Только при нажатии кнопки Update происходила передача данных из DataSet в саму базу данных. Не следует путать объект DataSet c оперативной памятью компьютера - загруженная таблица не находится в оперативной памяти компьютера.
Представьте себе, что вы обслуживаете гипотетическую доску объявлений. Каждое утро вы берете обычный бумажный блокнот, записываете в него все свежие объявления, хранящиеся в централизованном банке данных, и отправляетесь к доске. Вы переписываете из блокнота на доску все объявления, а в блокнот записываете все те объявления, которые были добавлены на доску посетителями. Затем вы возвращаетесь в DataSet. В этом процессе самым важным - для вас, конечно, не для централизованного банка данных, - будет ваш блокнот. Аналогично, класс DataSet является ключевым во всей модели классов ADO .NET.
DataSet состоит из объектов типа DataTable и объектов DataRelation. В коде к ним можно обращаться как к свойствам объекта DataSet, т.е., используя Tables возвращает объект типа DataTableCollection, который содержит все объекты DataTable используемой базы данных.
Объекты DataTable используются для представления таблиц в DataSet. DataTable представляет одну таблицу из базы данных. В свою очередь, DataTable составляется из объектов DataColumn.
DataColumn - это блок для создания схемы DataTable. Каждый объект DataColumn имеет свойство DataType, которое определяет тип данных, содержащихся в каждом объекте DataColumn. Например, вы можете ограничить тип данных до целых, строковых и десятичных чисел. Поскольку данные, содержащиеся в DataTable, обычно переносятся обратно в исходный источник данных, вы должны согласовывать тип данных с источником.
Объект DataSet имеет также свойство Relations, возвращающее коллекцию DataRelationCollection, которая в свою очередь состоит из объектов DataRelation. Каждый объект DataRelation выражает отношение между двумя таблицами (сами таблицы связаны по какому-либо полю (столбцу). Следовательно, эта связь осуществляется через объект DataColumn ).
Коллекция Rows объекта DataTable возвращает набор строк (записей) заданной таблицы. Эта коллекция используется для изучения результатов запроса к базе данных. Мы можем обращаться к записям таблицы как к элементам простого массива.
DataSet - это специализированный объект, содержащий образ базы данных. Для осуществления взаимодействия между DataSet и источником данных используется объект типа DataAdapter. Само название этого объекта - адаптер, преобразователь, - указывает на его природу. DataAdapter содержит метод Fill() для обновления данных из базы и заполнения DataSet.
Объект DBConnection осуществляет связь с источником данных. Эта связь может быть одновременно использована несколькими командными объектами. Объект DBCommand позволяет послать базе данных команду (как правило, команду SQL или хранимую процедуру). Объекты DBConnection и DBCommand иногда создаются неявно в момент создания объекта DataSet, но их также можно создавать явным образом.
Когда мы перетаскиваем на форму элемент управления, Visual Studio .NET автоматически генерирует код, описывающий этот элемент. Если при размещении кнопок, текстовых полей и других элементов управления создавать их программно нецелесообразно, то при работе с элементами данных все как раз наоборот - лучше всего создавать все объекты ADO .NET вручную, что обеспечивает большую гибкость приложения. Тем не менее на первых порах использования ADO .NET полезно работать с визуальной средой разработки.
Рассмотрим работу с базой данных Microsoft Acсess
| Microsoft Access, база данных xtreme | Microsoft SQL, база данных NorthwindCS |
Запустите Visual Studio .NET, создайте новый проект, тип проекта - Windows Application.
| Назовите его VisualDataMDB | Назовите его VisualDataSQL |
Размещаем на создавшейся форме элемент управления (рис 2.8) На вкладке Data находятся все элементы управления для работы с ADO.NET
Поместите на форму объект OleDbDataAdapter |
Поместите на форму объект SqlDataAdapter |
Перед нами появляется мастер настройки элемента управления. Для (рис 2.9) Поставщик данных Microsoft OLE DB Provider for SQL Server
Нажимаем кнопку "Далее" (или переходим на вкладку "Подключение") (рис. 2.10).
(рис 2.10) Определение параметров подключенияДля подключения к базе данных SQL, расположенной на вашем компьютере, в пункте 1 вводим ( local ) или просто точку - ".". В пункте 2 используем учетные сведения системы: по умолчанию пароль учетной записи администратора SQL Server - пустой. В пункте 3 выбираем базу данных NorthwindCS.
В следующем шаге мастера - определение типа запроса. Параметры, предлагаемые мастером, будут отличаться (рис. 2.11 и рис. 2.12):

(рис 2.12) Определение типа запросов объекта OleDbDataAdapter(рис 2.11) Определение типа запросов объекта SqlDbDataAdapterДля базы данных Microsoft Access мы можем только использовать SQL-запросы - другие значения не активны. Для базы данных Microsoft SQL Server мы можем либо применять SQL-запросы, либо создать новую хранимую процедуру ( stored procedure ), либо использовать существующую хранимую процедуру. Различия подобного рода определяются типом баз данных. Для объекта SqlDataAdapter оставляем значение, предложенное по умолчанию: использование SQL-запросов.
В следующем шаге - создание SQL-запросов (Generate OleDbDataAdapter:
(рис 2.13) Добавление таблицы в окно Построителя запросов Выбираем таблицу Customer ( Customers ), нажимаем кнопку Add и затем Close. Затем в окне Query Builder выбираем все столбцы (All Columns), как показано на рис. 2.14:
(рис 2.14) Добавление столбцов. Поставив галочку напротив пункта (All Columns), мы извлекаем все столбцы из таблицыНажимаем кнопку OK. В окне "Generate the
SELECT
Customer.*
FROM
Customer
|
SELECT
Customers.*
FROM
Customers
|
Обратите внимание, что синтаксис этого запроса несущественно отличается от "классического" SQL- запроса, рассмотренного выше.
Нажимаем кнопку Next. В окне "Обзор результатов мастера" (View Wizard Results) приводится список результатов работы мастера. Вид этого списка может отличаться, как это изображено на рис. 2.15 и 2.16:

(рис 2.16) Список результатов работы мастера объекта OleDbDataAdapter(рис 2.15) Список результатов работы мастера объекта SqlDbDataAdapterЧем обусловлено это различие? Для базы данных Access мастером создана возможность не только просмотра данных из базы данных - SQL-запрос SELECT, но и возможность ее изменения - запросы INSERT, UPDATE, DELETE. Для базы данных SQL Server создана лишь возможность просмотра базы данных. Для изменения данных необходимо проходить авторизацию (см. рис. 2.10) с учетной записью администратора базы данных.
Нажимаем кнопку Finish. Для объекта OleDbDataAdapter возникает окно (см. рис. 2.6), которое мы уже описывали выше.
Мастер создал на панели компонент по два элемента: oleDbDataAdapter1 и oleDbConnection1 для VisualDataMDB и sqlDbDataAdapter1 и sqlDbConnection1 для VisualDataSQL. oleDbDataAdapter1 (или sqlDbDataAdapter1 ) является основным компонентом типа OleDbData Adapter (или SqlDataAdapter ), который мы создавали при помощи мастера. Объект oleDbConnection1 (или sqlDbConnection1 ) был создан мастером как необходимый элемент подключения к базе. Образно говоря, мы получили адаптер ( DataAdapter1 ) и вилку ( Connection1 ) для подключения к источнику данных. Теперь нам необходимо добавить объект DataSet - тот самый "буфер", в котором будет храниться информация, полученная из базы данных. Щелкаем на oleDbDataAdapter1 (или sqlDbDataAdapter1 ), для его выделения. Открываем свойства этого элемента. На информационной панели щелкаем на ссылку "Generate DataSet" для создания объекта
(рис 2.17) Создание DataSetВ появившемся окне "Generate DataSet" задаем имена - dsCustomer и dsCustomers соответственно.
Итак, все "невидимые" части механизма подключения к базе данных у нас уже есть. Осталось теперь связать видимый интерфейс с данными. Объектом, отображающим данные на форме, у нас является dataGrid1. В свойстве этого элемента DataSource (источник данных) выбираем в качестве источника созданный объект dsCustomer1 (рис. 2.18).
(рис 2.18) Определение источника данных для элемента управления dataGrid1На форме в режиме дизайна у нас немедленно появилась символическая таблица со знаком (+). Последнее, что нам осталось сделать, - это заполнить объект DataSet (здесь - dsCustomer1 ). Переходим в код форм и вносим соответствующие добавления:
using System.Data.OleDb;
// Подключаем пространство имен для работы с поставщиком OleDb
private void Form1_Load(object sender, System.EventArgs e)
{
oleDbDataAdapter1.Fill(dsCustomer1);
}
using System.Data.SqlClient;
// Подключаем пространство имен для работы с поставщиком SQL
private void Form1_Load(object sender, System.EventArgs e)
{
sqlDataAdapter1.Fill(dsCustomers1);
}
В обоих случаях в методе загрузки формы вызываем метод Fill объекта oleDbDataAdapter1 (или sqlDbDataAdapter1 ) и передаем ему в качестве параметра dsCustomer1. Опять же, говоря образно, мы "заливаем" данные из адаптера в DataSet, который затем распоряжается ими - здесь мы определили, что DataSet выступает в качестве источника данных для dataGrid1.
Запустите приложения. Щелкните на знак (+), а затем на ссылку "Customer". Готовые приложения будут иметь следующий вид (рис. 2.19 и 2.20):

(рис 2.20) Готовое приложение VisualDataMDB(рис 2.19) Готовое приложение VisualDataSQLВ программном обеспечении к курсу вы найдете эти
В состав Visual Studio .NET входит замечательный инструмент управления и обзора подключениями к базам данных -
(рис 2.21) Добавление соединения Появляется окно мастера "Свойства связи с данными", с которым мы уже встречались (см. рис. 2.2 и 2.3). Создайте самостоятельно подключение к базе данных xtreme - после того как вы это сделаете, оно появится в списке всех подключений окна
(рис 2.22) В окне Server Explorer выводятся все созданные подключения к базам данныхЩелкните на знак (+) около названия подключения, откройте Tables, выберите таблицу Customer и перетащите ее на форму (рис. 2.23).
(рис 2.23) Содержимое базы данных xtremeПри появлении уже знакомого окна расположения пароля (см. рис. 2.6) выбираем "Include Password".
На панели компонент формы появились два элемента: oleDb Connection1 и oleDbDataAdapter1. Выделяем щелчком oleDbDataAdapter1, открываем его свойства, на информационной панели нажимаем "Generate DataSet". Называем объект "DataSet dsCustomer" и нажимаем "ОК". Помещаем на форме элемент управления DataGrid, в свойствах этого элемента указываем расположение Dock - Fill, DataSource - dsCustomer и переходим в код формы. Добавляем уже знакомый нам код:
private void Form1_Load(object sender, System.EventArgs e)
{
oleDbDataAdapter1.Fill(dsCustomer1);
}
Запускаем приложение. Его внешний вид ничем не отличается от приложения, рассмотренного в предыдущем примере.
Созданное подключение к базе данных xtreme теперь будет отображаться во всех последующих проектах в окне
Вы также можете использовать окно Solution Explorer для быстрого просмотра содержимого баз данных и - если подключение было создано с правами администратора - изменения их. Откройте нужную таблицу и просто дважды щелкните на нее (рис. 2.24):
(рис 2.24) Просмотр таблицы Customers базы данных NorthwindCS
Мы рассмотрели создание приложений для работы с базами данных с использованием различных мастеров. Однако разрабатывать такие приложения можно также без использования визуальной среды. Создадим такие же приложения, как и в предыдущем примере.
Будет работать с теми же самыми таблицами.
| Microsoft Access, база данных xtreme Таблица Customer | Microsoft SQL, база данных NorthwindCS Таблица Customers. |
Запустите Visual Studio .NET, создайте новый проект, тип проекта - Windows Application.
| Назовите его ProgrammDataMDB | Назовите его ProgrammDataSQL |
Размещаем на создавшейся форме элемент управления DataGrid, свойству Dock устанавливаем значение "Fill". Переходим в код формы. Подключаем соответствующие пространства имен:
using System.Data.OleDb; |
using System.Data.SqlClient; |
В конструкторе формы после InitializeComponent создаем объект DataAdapter:
public Form1()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();
OleDbDataAdapter dataAdapter =
new OleDbDataAdapter(CommandText, ConnectionString);
}
public Form1()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();
SqlDataAdapter dataAdapter =
new SqlDataAdapter(CommandText, ConnectionString);
}
В качестве параметров DataAdapter мы передаем CommandText и ConnectionString. Переменная типа string CommandText представляет собой обычный SQL-запрос на выборку из таблицы Customer, а переменная типа СonnectionString - это так называемая строка подключения, в которой указываются расположение базы данных, ее название, параметры авторизации и проч. Далее мы рассмотрим более подробно эти строки. Как составить эти переменные? Можно, конечно, написать вручную, но мы сейчас воспользуемся строчками, сгенерированными мастером. Откройте предыдущие проекты - VisualDataMDB и VisualDataSQL. Перейдите в код формы. Раскройте область Windows
Для CommandText:
this.oleDbSelectCommand1.CommandText = @"SELECT Address1, Address2, City, [Contact First Name], [Contact Last Name], [Contact Position], [Contact Title], Country, [Customer Credit ID], [Customer ID], [Customer Name], [E-mail], Fax, [Last Year's Sales], Phone, [Postal Code], Region, [Web Site] FROM Customer";
this.sqlSelectCommand1.CommandText = "SELECT CustomerID, CompanyName, ContactName, ContactTitle, Address, City, Region, PostalCode, Country, Phone, Fax FROM Customers";
Для
this.oleDbConnection1.ConnectionString = @" Jet OLEDB:Global Partial Bulk Ops=2;Jet OLEDB:Registry Path=; Jet OLEDB:Database Locking Mode=1; Jet OLEDB:Database Password=;Data Source=""E:\Program Files\Microsoft Visual Studio .NET 2003\Crystal Reports\Samples\Database\xtreme.mdb" ";Password=;Jet OLEDB:Engine Type=5;Jet OLEDB:Global Bulk Transactions=1;Provider=""Microsoft.Jet.OLEDB.4.0"";Jet OLEDB:System database=;Jet OLEDB:SFP=False;Extended Properties=; Mode=Share Deny None;Jet OLEDB:New Database Password=;Jet OLEDB:Create System Database=False;Jet OLEDB:Don'Jet Copy Locale on Compact=False;Jet OLEDB:Compact Without Replica Repair=False;User ID=Admin;Jet OLEDB:Encrypt Database=False";
this.sqlConnection1.ConnectionString = "workstation id=7EA2B2F6068D473;packet size=4096;integrated security=SSPI; data source=\"(local) \";persist security info=False; initial catalog=NorthwindCS";
Скопируйте эти строчки, начиная от названия самих переменных, затем в коде форм ProgrammDataMDB и ProgrammDataSQL в классе Form 1 объявите две переменные по две переменных типа string и вставьте скопированные значения:
string CommandText = @"SELECT Address1, Address2, City, [Contact First Name], [Contact Last Name], [Contact Position], [Contact Title], Country, [Customer Credit ID], [Customer ID], [Customer Name], [E-mail], Fax, [Last Year's Sales], Phone, [Postal Code], Region, [Web Site] FROM Customer";
string ConnectionString = @"Jet OLEDB:Global Partial Bulk Ops=2;Jet OLEDB:Registry Path=;Jet OLEDB:Database Locking Mode=1; Jet OLEDB:Database Password=;Data Source=""E:\Program Files\Microsoft Visual Studio .NET 2003\Crystal Reports\Samples\Database\xtreme.mdb"";Password=; Jet OLEDB:Engine Type=5;Jet OLEDB:Global Bulk Transactions=1;Provider=""Microsoft.Jet.OLEDB.4.0""; Jet OLEDB:System database=;Jet OLEDB:SFP=False;Extended Properties=; Mode=Share Deny None;Jet OLEDB:New Database Password=; Jet OLEDB:Create System Database=False;Jet OLEDB:Don' Jet Copy Locale on Compact=False;Jet OLEDB:Compact Without Replica Repair=False; User ID=Admin;Jet OLEDB:Encrypt Database=False";
string CommandText = "SELECT CustomerID, CompanyName, ContactName, ContactTitle, Address, City, Region, PostalCode, Country, Phone, Fax FROM Customers";
string ConnectionString = "workstation id=7EA2B2F6068D473;packet size=4096;integrated security=SSPI;data sou" + "rce=\"(local)\";persist security info=False;initial catalog=NorthwindCS";
Обратите внимание на названия переменных CommandText и ConnectionString. Когда мы создаем объект DataAdapter, в качестве параметров мы можем передать названия строк, таких как cmdText и conString, или даже и cns - совершенно равноправно, не забыв, конечно же, назвать также эти переменные в классе Form1. Но сама среда Visual Studio .NET генерирует эти строки именно с такими названиями - CommandText и ConnectionString, поэтому если вы пишите их не вручную, то облегчаете работу, называя их так же, как и среда.
Возвращаемся к нашим приложениям - ProgrammDataMDB и ProgrammDataSQL. Дальнейший код будет совершенно одинаковым для обоих приложений.
Итак, создаем объект DataSet:
DataSet ds = new DataSet();
Заполняем таблицу Customer объекта ds данными из базы:
dataAdapter.Fill(ds, "Customer");
Cвязываем источник данных объекта dataGrid1 (который мы нанесли на форму в режиме дизайна) с таблицей Customer объекта ds:
dataGrid1.DataSource = ds.Tables["Customer"].DefaultView;
Все! Запускаем оба приложения. Если вы были внимательны в самом начале, то заметили, что в базе данных xtreme таблица называется Customer, а в базе данных NorthwindCS - Customers ( "s" на конце). Тем не менее код работает для обоих приложений. В чем же дело? Таблица, которую мы называем "Customer", при вызове метода Fill объекта dataAdapter может быть названа как угодно - ее содержимое будет представлять собой извлекаемую таблицу из базы данных. При указании источника данных ( DataSource ) для объекта dataGrid1 мы ссылаемся именно на таблицу Customer, которая была создана при вызове метода Fill. Точнее говоря, эта таблица определена в объекте DataSet, а именно к нему мы и обращаемся для заполнения данными нашей формы в соответствии с моделью ADO .NET. Чтобы убедиться в этом, попробуйте такой код:
DataSet ds = new DataSet(); dataAdapter.Fill(ds, "Bezimyannaya"); dataGrid1.DataSource = ds.Tables["Bezimyannaya"].DefaultView;
По-прежнему все работает. Означает ли это, что можно небрежно относиться к названию таблицы в DataSet? Нет - в нашем учебном примере мы с самого начала извлекали только одну таблицу из базы данных. В реальных приложениях приходится иметь дело с десятками таблиц, и будет возникать большая путаница, если называть таблицы как попало. Поэтому следует давать названия таблицам в объекте DataSet названия тех таблиц, образы которых они представляют.
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Data.OleDb;
namespace ProgrammDataMDB
{
/// <summary>
/// Summary description for Form1.
/// </summary>
public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.DataGrid dataGrid1;
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;
string CommandText = @"SELECT Address1, Address2, City,
[Contact First Name], [Contact Last Name], [Contact Position],
[Contact Title], Country, [Customer Credit ID], [Customer ID],
[Customer Name], [E-mail], Fax, [Last Year's Sales],
Phone, [Postal Code], Region, [Web Site] FROM Customer";
string ConnectionString = @"Jet OLEDB:Global Partial Bulk Ops=2;Jet
OLEDB:Registry Path=;Jet OLEDB:Database Locking Mode=1;Jet
OLEDB:Database Password=;Data Source=""E:\Program
Files\Microsoft Visual Studio .NET 2003\Crystal
Reports\Samples\Database\xtreme.mdb"";Password=;Jet
OLEDB:Engine Type=5;Jet OLEDB:Global Bulk
Transactions=1;Provider=""Microsoft.Jet.OLEDB.4.0"";
Jet OLEDB:System database=;Jet OLEDB:SFP=False;Extended
Properties=;Mode=Share Deny None;Jet OLEDB:New Database Password=;
Jet OLEDB:Create System Database=False;Jet OLEDB:Don'
Jet Copy Locale on Compact=False;Jet OLEDB:Compact Without
Replica Repair=False;User ID=Admin;
Jet OLEDB:Encrypt Database=False";
public Form1()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();
OleDbDataAdapter dataAdapter =
new OleDbDataAdapter(CommandText, ConnectionString);
DataSet ds = new DataSet();
dataAdapter.Fill(ds, "Bezimyannaya");
dataGrid1.DataSource = ds.Tables["Bezimyannaya"].DefaultView;
//
// TODO: Add any constructor code after InitializeComponent call
//
}
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
Windows Form Designer generated code
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.Run(new Form1());
}
private void Form1_Load(object sender, System.EventArgs e)
{
}
}
}
Полный листинг программы - подключение к базе данных NorthwindCS:
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Data.SqlClient;
namespace ProgrammDataSQL
{
/// <summary>
/// Summary description for Form1.
/// </summary>
public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.DataGrid dataGrid1;
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;
string CommandText = "SELECT CustomerID, CompanyName,
ContactName, ContactTitle, Address, City, Region," +
" PostalCode, Country, Phone, Fax FROM Customers";
string ConnectionString = "workstation id=7EA2B2F6068D473;packet
size=4096;integrated security=SSPI;data sou" +
"rce=\"(local)\";persist security info=False;initial
catalog=NorthwindCS";
public Form1()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();
SqlDataAdapter dataAdapter =
new SqlDataAdapter(CommandText, ConnectionString);
DataSet ds = new DataSet();
dataAdapter.Fill(ds, "Customer");
dataGrid1.DataSource = ds.Tables["Customer"].DefaultView;
//
// TODO: Add any constructor code after InitializeComponent call
//
}
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
Windows Form Designer generated code
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.Run(new Form1());
}
private void Form1_Load(object sender, System.EventArgs e)
{
}
}
}
Для извлечения таблиц и содержащихся в них данных используются SQL-запросы. Переменная CommandText содержит в себе SQL-запрос, синтаксис которого адаптирован для данного поставщика данных. Мы можем управлять извлечением данных, изменяя строку CommandText. Скопируйте папку проекта ProgrammDataSQL и назовите ее CommandText. Запустите проект и перейдите в код формы. Изменим string СommandText так, чтобы извлекать в DataGrid только поля CustomerID, ContactName, Country и Phone. Для этого удалим ненужные поля, в результате получится следующий SQL-запрос:
string CommandText = "SELECT CustomerID, ContactName, Country, Phone FROM Customers";
Запустите приложение. Теперь на форму выводятся только соответствующие четыре поля (рис. 2.25):
(рис 2.25) Ограничение выводимых полей Выведем теперь все записи клиентов, имена которых начинаются на "М":
string CommandText = "SELECT CustomerID, ContactName, Country, Phone FROM Customers where ContactName like 'M%'";
Запускаем приложение. Запрос выбрал только записи на букву "M" (рис. 2.26).
(рис 2.26) Ограничение выводимых полейВы можете использовать все возможности языка SQL для отбора данных и модификации строки CommandText для получения нужного результата. Не пробуйте только использовать команды insert, update или delete - изменение записей в базе данных мы рассмотрим позже.
В программном обеспечении к курсу вы найдете приложение СommandText (Code\Glava1\ СommandText).
Строка соединения ConnectionString определяет параметры, необходимые для установления соединения с источником данных. Строка соединений при использовании мастеров генерируется средой, но можно (и желательно - во избежание неточностей и ошибок) писать эту строчку вручную. Рассмотрим еще раз строки соединения, которые были созданы при подключении к базам данных xtreme и Northwind.
База данных xtreme, проект ProgrammDataMDB:
string ConnectionString = @"Jet OLEDB:Global Partial Bulk Ops=2; Jet OLEDB:Registry Path=;Jet OLEDB:Database Locking Mode=1; Jet OLEDB:Database Password=;Data Source=" "E:\Program Files\Microsoft Visual Studio .NET 2003\Crystal Reports\Samples\Database\xtreme.mdb"";Password=; Jet OLEDB:Engine Type=5;Jet OLEDB:Global Bulk Transactions=1;Provider=""Microsoft.Jet.OLEDB.4.0""; Jet OLEDB:System database=;Jet OLEDB:SFP=False;Extended Properties=; Mode=Share Deny None;Jet OLEDB:New Database Password=; Jet OLEDB:Create System Database=False;Jet OLEDB:Don' Jet Copy Locale on Compact=False; Jet OLEDB:Compact Without Replica Repair=False;User ID=Admin; Jet OLEDB:Encrypt Database=False";
База данных NorthwindCS, проект ProgrammDataSQL:
string ConnectionString = "workstation id=7EA2B2F6068D473;packet size=4096; integrated security=SSPI;data sou" + "rce=\"(local)\";persist security info=False; initial catalog=NorthwindCS";
В этих строках через точку с запятой просто перечисляются параметры соединения. В таблице 2.1 приводятся основные значения этих параметров.
| Параметр | Описание |
|---|---|
Provider (Поставщик) |
Свойство применяется для установки или возврата имени поставщика для соединения, используется только для объектов OleDbConnection |
Connection Timeout или Connect Timeout (Время ожидания связи) |
Длительность времени ожидания связи с сервером перед завершением попытки и генерацией исключения в секундах. По умолчанию 15 |
Initial Catalog (Исходный каталог) |
Имя базы данных |
Data Source (Источник данных) |
Имя используемого SQL-сервера, когда установлено соединение, или имя файла базы данных Microsoft Access |
Password (Пароль) |
Пользовательский пароль для учетной записи SQL Server |
User ID (Пользовательский ID) |
Пользовательское имя для учетной записи SQL Server |
Workstation ID |
Имя рабочей станции или компьютера |
Integrated Security или Trusted Connection (Интегрированная безопасность или Доверительное соединение) |
Параметр, который определяет, является ли соединение защищенным. True, False и SSPI - возможные значения. (SSPI - эквивалент True) |
Persist Security Info (Удержание защитной информации |
Когда установлено False, нуждающаяся в защите информация, такая как пароль, не возвращается как часть соединения, если связь установлена или когда-либо была установленной. Выставление этого свойства в True может быть рискованным в плане безопасности. По умолчанию False |
При создании мастером строки ConnectionString происходит генерирование большого количества лишних параметров. Нельзя сказать, что они не нужны, просто мастер предусматривает все возможности использования этого подключения и вставляет соответствующие значения. В действительности необходимых значений для простого извлечения данных всего несколько:
Скопируйте папки с проектами ProgrammDataMDB и Programm DataSQL. Переименуйте копии в ConnStringMDB и ConnStringSQL. Измените значения ConnectionString следующим образом:
База данных xtreme, проект ConnStringMDB:
string ConnectionString = @"Provider=""Microsoft.Jet.OLEDB.4.0""; Data Source=""E:\Program Files\Microsoft Visual Studio .NET 2003\Crystal Reports\Samples\Database\xtreme.mdb""; User ID=Admin;Jet OLEDB:Encrypt Database=False";
База данных NorthwindCS, проект ConnStringSQL:
string ConnectionString = "workstation id=7EA2B2F6068D473;integrated security=SSPI; data source=\"(local)\";persist security info=False; initial catalog=NorthwindCS";
Мы значительно сократили количество параметров, получив прежнюю функциональность приложений.
Где определяется строка подключения, когда мы создаем объект DataAdapter не программно, а с помощью мастера? Среда генерирует строку подключения вместе с кодом для DataAdapter, и в этом нетрудно убедиться. Запустите приложение, которое мы делали, вообще ничего не зная об объектах ADO .NET - DataWizardMDB. Перейдите в код формы, откройте область Windows
this.oleDbConnection1.ConnectionString = @"Jet OLEDB:Global Partial Bulk Ops=2; Jet OLEDB:Registry Path=;Jet OLEDB:Database Locking Mode=1; Jet OLEDB:Database Password=;Data Source=" "D:\Uchebnik\Code\Glava4\RBProduct.mdb" ";Password=;Jet OLEDB:Engine Type=5; Jet OLEDB:Global Bulk Transactions=1;Provider=" "Microsoft.Jet.OLEDB.4.0""; Jet OLEDB:System database=;Jet OLEDB:SFP=False;Extended Properties=; Mode=Share Deny None;Jet OLEDB:New Database Password=; Jet OLEDB:Create System Database=False;Jet OLEDB:Don' Jet Copy Locale on Compact=False; Jet OLEDB:Compact Without Replica Repair=False; User ID=Admin;Jet OLEDB:Encrypt Database=False";
Когда мы переносим объект DataAdapter из панели инструментов Toolbox (со вкладки Data) на форму, вместе с ним образуется объект DBConnection, в свойствах которого указывается строка ConnectionString и другие параметры подключения (рис. 2.27):
(рис 2.27) Свойства объекта sqlConnection1 проекта VisualDataSQL
Большинство источников данных поддерживает ограниченное количество соединений. Так, база данных Microsoft Access может поддерживать одновременную работу не более чем с 255 пользователями. При попытке обращения к базе данных, лимит соединений которой исчерпан, пользователь не получит нужной ему информации и будет вынужден ждать освобождения соединения. Задача разработчика заключается в минимизации времени связи с базой данных, поскольку соединение занимает полезные системные ресурсы.
Когда вы вызываете у объекта DataAdapter метод (например, Fill ), то он сам проверяет, открыто ли соединение. Если соединения нет, то DataAdapter открывает соединение, выполняет задачи и затем закрывает соединение.
Явное управление соединением - лучший подход к работе с базами данных. Он обладает рядом преимуществ:
Для явного управления соединением используется объект Connection. Создайте новый проект и назовите его ConnectionMDB. Перетащите элемент управления DataGrid из панели инструментов Toolbox и установите свойству Dock значение Fill. Перейдите в код формы. Подключаем пространство имен:
using System.Data.OleDb;
В конструкторе Form1 после InitializeComponent создаем объект Connection:
OleDbConnection conn = new OleDbConnection(ConnectionString);
В качестве параметра объекту conn передается строка подключения ConnectionString.
Можно также устанавливать строку подключения через свойство созданного объекта сonn:
OleDbConnection conn = new OleDbConnection(); conn.ConnectionString = ConnectionString;
Теперь нам необходимо определить параметры самой строки ConnectionString. Вы можете сделать это вручную или скопировав код из приложения ConnStringMDB (подключаться будем к базе данных xtreme).
string ConnectionString = @"Provider=""Microsoft.Jet.OLEDB.4.0""; Data Source=""E:\Program Files\Microsoft Visual Studio .NET 2003\Crystal Reports\Samples\Database\xtreme.mdb"";User ID=Admin;Jet OLEDB:Encrypt Database=False";
Теперь можно устанавливать соединение, вызывая метод Open объекта Connection:
OleDbConnection conn = new OleDbConnection(); conn.ConnectionString = ConnectionString; conn.Open();
Объект Command применяется для выполнения SQL-запросов к источнику данных. Чтобы выполнить запрос, свойству Connection объекта Command следует задать объект - имя созданного Connection:
OleDbConnection conn = new OleDbConnection(); conn.ConnectionString = ConnectionString; conn.Open(); OleDbCommand myCommand = new OleDbCommand(); myCommand.Connection = conn;
Объект Connection также предоставляет метод CreateCommand, позволяющий упростить данный процесс - этот метод возвращает новый объект Command, уже инициализированный для использования вашего объекта Connection:
OleDbConnection conn = new OleDbConnection(); conn.ConnectionString = ConnectionString; conn.Open(); OleDbCommand myCommand = conn.CreateCommand();
Эти два способа совершенно эквивалентны.
Теперь нам следует определить SQL-запрос, который будет извлекать данные. Как и раньше, строкой, в которой будет содержаться этот запрос, будет CommandText. Объявляем переменную CommandText, извлекающую все столбцы таблицы Customer:
string сommandText = @"SELECT Address1, Address2, City, [Contact First Name], [Contact Last Name], [Contact Position], [Contact Title], Country, [Customer Credit ID], [Customer ID], [Customer Name], [E-mail], Fax, [Last Year's Sales], Phone, [Postal Code], Region, [Web Site] FROM Customer";
Объект myСommand имеет свойство, которое так и называется - CommandText. Чтобы избежать путаницы, изменим название переменной - CommandText на commandText (с маленькой буквы):
myCommand.CommandText = commandText;
Создаем объект OleDbDataAdapter:
OleDbDataAdapter dataAdapter = new OleDbDataAdapter();
Объект dataAdapter имеет свойство SelectCommand в котором мы и будем указывать объект myCommand:
dataAdapter.SelectCommand = myCommand;
Создаем объект DataSet:
DataSet ds = new DataSet();
Заполняем ds данными из dataAdapter:
dataAdapter.Fill(ds, "Customers");
Указываем источник данных DataSource для dataGrid1:
dataGrid1.DataSource = ds.Tables["Customers"].DefaultView;
Закрываем соединение явным образом:
conn.Close();
Все! Запускаем приложение. Мы получили уже знакомый результат, но теперь мы действительно управляем всеми объектами, работающими с данными.
Полный листинг проекта ConnectionMDB:
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Data.OleDb;
namespace ConnectionMDB
{
/// <summary>
/// Summary description for Form1.
/// </summary>
public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.DataGrid dataGrid1;
string ConnectionString =
@"Provider=""Microsoft.Jet.OLEDB.4.0"";
Data Source=""E:\Program Files\Microsoft Visual Studio
.NET 2003\Crystal Reports\Samples\Database\xtreme.mdb"
";User ID=Admin;Jet OLEDB:Encrypt Database=False";
string commandText = @"SELECT Address1, Address2, City,
[Contact First Name], [Contact Last Name], [Contact Position],
[Contact Title], Country, [Customer Credit ID], [Customer ID],
[Customer Name], [E-mail], Fax, [Last Year's Sales],
Phone, [Postal Code], Region, [Web Site] FROM Customer";
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;
public Form1()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();
OleDbConnection conn = new OleDbConnection(ConnectionString);
//OleDbConnection conn = new OleDbConnection();
//conn.ConnectionString = ConnectionString;
conn.Open();
OleDbCommand myCommand = new OleDbCommand();
myCommand.Connection = conn;
myCommand.CommandText = commandText;
//OleDbCommand myCommand = conn.CreateCommand();
OleDbDataAdapter dataAdapter = new OleDbDataAdapter();
dataAdapter.SelectCommand = myCommand;
DataSet ds = new DataSet();
dataAdapter.Fill(ds, "Customers");
dataGrid1.DataSource = ds.Table
["Customers"].DefaultView;
conn.Close();
//
// TODO: Add any constructor code after InitializeComponent call
//
}
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
Windows Form Designer generated code
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.Run(new Form1());
}
private void Form1_Load(object sender, System.EventArgs e)
{
}
}
}
Сравните использование строк ConnectionString и connectingText объектом myCommand с аналогичным использованием объектом DataAdapter ( ProgrammDataMDB и ProgrammDataSQL ).
Создание объекта Connection для базы данных SQL принципиально не отличается от примера, рассмотренного выше. В следующем фрагменте кода описываются те же объекты Connection и Command:
using System.Data.SqlClient; string CommandText = "SELECT CustomerID, CompanyName, ContactName, ContactTitle, Address, City, Region, PostalCode, Country, Phone, Fax FROM Customers"; string connectionString = "workstation id=7EA2B2F6068D473; integrated security=SSPI;data source=\"(local)\"; persist security info=False;initial catalog=NorthwindCS"; SqlConnection conn = new SqlConnection(connectionString); //SqlConnection conn = new SqlConnection(); //conn.ConnectionString = ConnectionString; conn.Open(); SqlCommand myCommand = new SqlCommand(); myCommand.Connection = conn; myCommand.CommandText = CommandText; //SqlCommand myCommand = conn.CreateCommand(); SqlDataAdapter dataAdapter = new SqlDataAdapter(); dataAdapter.SelectCommand = myCommand; DataSet ds = new DataSet(); dataAdapter.Fill(ds, "Customers"); dataGrid1.DataSource = ds.Tables["Customers"].DefaultView; conn.Close();
В программном обеспечении к курсу вы найдете приложения ConnectionMDB и ConnectionSQL (Code\Glava1\ ConnectionMDB и ConnectionSQL).
У вас наверняка могло сложиться впечатление, что использование визуальных средств Microsoft Visual Studio .NET для добавления и конфигурирования объектов ADO .NET несравненно проще и логичней, чем программный способ создания этих объектов. Однако это впечатление глубоко ошибочно. В действительности только последний пример может претендовать на завершенное приложение - все остальные являются своего рода вспомогательными модулями. Повторю, что только полностью вручную написанный код объектов ADO .NET позволяет создавать ясные, надежные и гибкие приложения.
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.