Книги, научные публикации Pages:     | 1 |   ...   | 2 | 3 | 4 | 5 | 6 |   ...   | 8 |

David Sceppa Microsoft Press Дэвид Москва 2003 Р Г Г If Р F г V А Л А - л г УДК 004.45 32.973.26-018.2 С28 Д. ...

-- [ Страница 4 ] --

Таблица 6-7. Событие объекта DataSet Событие Описание Наступает, если метод сгенерировал исключение Событие MergeFailed Событие позволяет обрабатывать любые ошибки, возникающие при использовании метода Merge объекта DataSet. Лично я так и не смог заставить это событие наступить. Возможно, у вас это получится.

Свойства объекта DataTable В табл. 6-8 перечислены наиболее часто используемые свойства объекта DataTable.

Таблица 6-8. Свойства объекта DataTable Свойство Тип данных Описание Boolean Определяет, ли регистр симво лов при сравнении строк DataRelationCollection Возвращает объекты DataRelation с дочер ними данными объекта DataTable Columns Содержит набор объектов входящих в состав объекта DataTable Constraints Содержит набор объектов вхо дящих в состав объекта DataTable DataSet DataSet Возвращает объект DataSet, в состав кото рого входит DataTable Возвращает объект DataView, который свя занные элементы управления получают от объекта DataTable Boolean Указывает, находится ли объект DataTable в режиме проектирования Содержит набор динамических свойств и Boolean Указывает, содержит ли ошибки Locale Определяет региональные параметры, ис пользуемые объектом DataTable при срав нении строк Namespace String Содержит пространство имен, которое ADO.NET использует при записи содержи мого DataTable в XML-файл или при загруз ке XML-данных в объект DataTable DataRelationCollection Возвращает объекты DataRelation с роди тельскими данными объекта DataTable Prefix String Содержит префикс имен, ис пользуемого ADO.NET при содер жимого DataTable в XML-файл или при за грузке XML-данных в объект DataTable ГЛАВА 6 Работа с объектами DataSet Таблица 6-8.

Свойство Тип данных Описание Массив объектов Содержит информацию о первичном ключе объекта Содержит набор объектов DataColumn, Rows входящих в состав DataTable Содержит имя объекта DataTable Свойство Свойство CaseSensitive объекта DataTable определяет, различается ли регистр сим волов при сравнении строк в объекте DataTable. Объект DataSet также предостав ляет свойство CaseSensitive.

Значение по умолчанию свойства CaseSensitive объекта DataTable Ч такое же, как значение одноименного свойства объекта DataSet. Если вы зададите значение свойства CaseSensitive объекта оно переопределит значение, наследуе мое от родительского объекта DataSet.

Значение по умолчанию свойства CaseSensitive объекта DataTable, который не относится к DataSet Ч False.

Свойства и Свойства и ParentRelations позволяют просматривать объекты с родительскими и дочерними отношениями текущего объекта DataTable.

Допустим, вы работаете с иерархией клиентов (customers), заказов (orders;

и сведений о заказах (order details) и у есть ссылка на объект DataTable с ин формацией о заказах. Тогда в наборе ParentRelations объект отношение между объектами DataTable Customers и Orders, а в набо ре ChildRelations Ч объект DataRelation, создающий отношение между объектами DataTable Orders и Order Details.

Свойство Columns Свойство Columns позволяет просматривать, добавлять, изменять и удалять объекты DataColumn. Оно возвращает объект содержащий объекты DataColumn из состава DataTable.

Обращаться к объектам DataColumn через свойство Columns можно по их (свойство или порядковому номеру (свойство Ordinal). Как обыч но, в последнем случае производительность Свойство Constraints Свойство Constraints позволяет добавлять, изменять и удалять оп ределенные на объекте DataTable ограничения. Оно возвращает объект Collection.

Обращаться к объектам DataColumn через свойство Columns можно по их имени (свойство или порядковому номеру в наборе. В последнем слу чае обеспечивается более высокая производительность, 230 Часть III Автономная работа с данными: объект DataSet Свойство DataSet Свойство DataSet возвращает одноименный объект, в состав которого DataTable. Если последний не относится к какому-либо объекту DataSet, данное свойство возвращает неинициализированный объект.

Свойство DataSet доступно только для чтения.

Свойство Если связать с объектом DataTable элемент управления, последний на самом деле будет связан с объектом возвращаемым свойством объекта DataTable. Так, следующий фрагмент кода Ч это фильтр, выводящий в элементе управления связанном с объектом только список клиентов из Испаттии (Spain). Независимо от фильтра, объект DataTable по-прежнему содер жит список клиентов.

Visual Basic = "Country = = tblCustomers Visual C# = "Country = = tblCustomers;

Подробнее об объекте Ч в главе 8.

Свойство Свойство DesignMode возвращает логическое значение, указывающее, находится ли объект DataTable в режиме проектирования. Это свойство полезно при напи сании кода в нестандартном элементе управления. Если объект исполь зуется в компоненте в период разработки, свойство DesignMode возвращает True.

В противном случае оно возвращает False.

Объект DataSet также предоставляет свойство DesignMode. Данное свойство доступно только для чтения.

Свойство Свойство объекта DataTable возвращает объект предназначенный для хранения разнообразных объектов.

Объекты DataSet, и Constraint также предоставляют свойство ExtendedProperties.

Подробнее о данном свойстве, включая пример кода, Ч в разделе этой главы, посвященном свойству ExtendedProperties объекта DataSet, Свойство HasErrors Свойство HasErrors возвращает логическое значение, указывающее, содержат ли объекты из состава ошибки. Если вы передаете в БД пакеты изменений и задали свойству объектов DataAdapter значение True, проверяйте по завершении передачи значение свойства HasErrors объектов ГЛАВА 6 DataSet Таким образом вы узнаете, все ли операции передачи изменений завер шились успешно.

DataSet и DataRoiv также предоставляют свойство Подробнее о действиях в случае ошибок при передаче изменений БД Ч в главе Свойство Locale Свойство Locale определяет, как сравнивает строки в объекте DataTabie, DataSet также предоставляет свойство Locale.

Подробнее о данном включая пример кода. Ч в разделе этой главы, Locale объекта DataSet, Свойство Если вам сколько примерно записей будет в объекте можно повысить производительность кода, задав, прежде чем заполнить DataTabie резуль татами запроса, значение свойства MinimumCapacity.

По умолчанию оно равно 50, т. е. ADO.NET резервирует объем памяти, доста точный для того, чтобы мог содержать 50 записей. Если вы пред ставляете себе примерное число записей в объекте DataTabie, то для производительности кода следует назначить свойству MinimumCapacity более точное Задавая при работе с объектами DataTabie данному свойству маленькое значение, вы также снижаете требования приложения к памяти.

Когда вы добавляете в объект DataTabie дополнительные записи, ошибок за нехватки памяти не возникает Ч ADO.NET просто запрашивает дополнитель ную память, и все.

Свойства Namespace и Prefix Свойства Namespace и Prefix позволяют указать для объекта DataTabie префикс и пространство имен XML. ADO.NET использует значения этих свойств при записи содержимого в XML-файл, а также при загрузке XML-документа в объект DataTabie.

Объекты DataSet и также обладают свойствами Namespace и Prefix, Подробнее о пространствах имен XML Ч в документации Свойство Свойство массив объектов DataColumn. составляющих пер вичный ключ объекта DataTabie.

У первичного ключа Ч два назначения. он играет роль ограниче ния на уникальность. Наличие двух объектов DataRoiv с одинаковыми значения ми полей первичного ключа невозможно. Предположим, у вас объект DataTabie с информацией о клиентах и вы определили первичный ключ на основе объекта DataColumn Если при добавлении в объект новой записи окажется, что у нее и одной из имеющихся записей одинаковые значения полей первичного ключа, ADO.NET сгенерирует исключение.

Кроме того, значения первичного ключа стоит использовать для поиска объек тов в объекте DataTabie при помощи метода Find набора Rows объекта DataTabie. Подробнее об этом Ч в главе 8.

232 Часть III Автономная работа с данными: объект DataSet модели Следующий фрагмент кода задает значение свойства объекта Visual Basic Dim As New = New DataColumnC) Visual DataTable tbl = new tbl.PrimaryKey = new Свойство Rows Свойство Rows возвращает объект содержащий объекты из состава DataTable. С помощью данного свойства удается добавлять объекты в а также обращаться к уже имеющимся объектам.

Для поиска объектов DataRow в объекте DataTable по порядковым номерам предназначен объект DataRowCollection. Подробнее о поиске объектов по значениям первичного ключа и другим критериям Ч в главе 8.

Свойство Свойство TableName содержит имя объекта DataTable. Значение этого свойства задается в конструкторе Когда вы сохраняете содержимое DataTable в XML-документ, свойство TableName используется в качестве имени тега для всех записей из DataTable.

Методы объекта DataTable В табл. 6-9 перечислены наиболее часто используемые методы объекта DataTable.

Таблица 6-9. Методы объекта DataTable Метод Описание Подтверждает все отложенные изменения в объекте DataTable Вызывается конструкторами Visual Studio перед добавлением в объект DataTable сведений схемы Отключает все ограничения при загрузке данных Clear Удаляет из DataTable все объекты Clone Создает новый объект DataTable с идентичной схемой, но без объектов DataRow Compute Возвращает значение агрегатного выражения, основываясь на содержи мом объекта DataTable Сору Создает новый объект DataTable с такой же схемой и объектами DataRow ГЛАВА 6 Работа с DataSet Таблица 6-9. (продолжение) Метод Описание конструкторами Visual Studio после добавления в объект сведений схемы Активирует ограничения после загрузки данных Возвращает новый объект DataTable с идентичной схемой, содержащий измененные записи оригинального объекта DataTable Возвращает массив объектов DataRow, содержащих ошибки Импортирует объект DataRow в объект DataTable Добавляет в объект DataTable новый объект DataRow, основываясь на содержимом массива Возвращает для объекта DataTable новый объект DataRow RejectChanges Отменяет все отложенные изменения в объекте DataTable Reset Восстанавливает оригинальное состояние объекта DataTable, в котором он находился до инициализации Select Возвращает массив объектов DataRow на основании заданного рия поиска Методы и RejectChanges Методы AcceptChanges и RejectChanges позволяют соответственно подтверждать и отбрасывать все отложенные изменения в объекте -DataTable.

Объекты DataSet и DataRow также обладают методами AcceptChanges и Reject Changes. Подробнее об этих методах Ч в разделе объекта DataSet этой главы.

Методы и Endlnit Методы Beginlnit и Endlnit вызываются конструкторами, поэтому их не надо ис пользовать непосредственно в коде.

Объект DataSet также обладает методами Beginlnit и Endlnit. Подробнее об этих методах Ч в разделе Методы объекта DataSet" этой главы, Методы и EndLoadData Если вы добавляете в объект DataTable группу объектов для повышения производительности кода следует применить методы BeginLoadData и EndLoadData.

При вызове метода BeginLoadData отключаются определенные на объекте Data ограничения. их можно средствами метода EndLoadData. Если в объекте DataTable есть записи, нарушающие какие-либо ограничения, при вы зове метода EndLoadData ADO.NET сгенерирует исключение Чтобы определить, какие именно записи нарушают ограничения, просмотрите возвращаемый методом GetErrors.

Метод Метод Clear позволяет удалить из объекта DataTable все объекты DataRow. Вызвать его быстрее, чем освободить оригинальный и создать новый объект DataTable с идентичной структурой.

Объект DataSet также предоставляет метод Clear.

9- 234 Часть III Автономная работа с данными: объект DataSet модели Методы Clone и Сору С помощью метода Сору создают новый объект DataTable, по структуре и содер жимому аналогичный оригинальному. Чтобы создать объект с идентич ной структурой, но без записей, воспользуйтесь методом Clone, Объект также обладает методами Clone и Сору.

Метод Compute Метод Compute позволяет выполнять запросы к отдельным объекта на основе критериев поиска.

Следующий фрагмент кода с помощью метода Compute подсчитывает число заказов, включающий chai, а также общее число заказанных единиц это го товара.

Visual Basic Dim strConn As String = & _ "Initial strSQL = "SELECT Quantity [Order da As New strConn) Dim As New Dim intNumChaiOrders As Integer Dim As Long intNumChaiOrders = "ProductID = = "ProductID = of orders that include chai: & intNumChaiOrders) number of units ordered: & Visual C# string strSQL, strConn;

strConn = + "Initial StrSQL = "SELECT OrderlD, ProductID, Quantity [Order OleDbDataAdapter da = new strConn);

DataTable tbl new int intNumChaiOrders;

Int intNumChaiOrders = (int) "ProductID = = (Int64) "ProductID = of orders that include chai: + ГЛАВА 6 Работа с объектами DataSet number of units ordered: + Метод Compute не агрегатные значения на основе ких столбцов, например * Тем не менее с помощью на выражении столбца удается вычислить произведение указанных см ол бцов и использовать этот основанный на выражении столбец в мемоде Count:

Метод возвращает результаты с использованием универсального типа данных Object. При вычислении значения средствами метода Compute вас, удивит тип данных, применяемый этим методом для хранения данных. Так.

тип данных столбца Quantity Ч 16-разрядное целое число, однако при вызове метод возвращает 64-разрядное целое число.

Если вы не знаете, какой тип данных выбрать для результатов мето да воспользуйтесь таким кодом:

Visual Basic Dim objRetVal As Object = = Visual C# objRetVal = "ProductlD = Метод Метод возвращает новый объект со оригинального объекта содержащий записи оригинального объек та DataTable с отложенными изменениями. Подробнее об этом Ч в главе Объект DataSet также предоставляет метод Метод Метод GetErrors позволяет в случае нарушения ограничений или неудачной пере дачи обновлений в БД обращаться к объектам содержащим ошибки, Данный метод возвращает массив объектов DataRoiv, Методы и Метод принимает объект и добавляет его в объект DataTable, Метод LoadDataRow принимает в качестве первого аргумента массив, элемен ты которого соответствуют элементам набора Columns объекта DataTable. Второй аргумент Ч это логическое значение, управляющее свойством RowState нового объекта Чтобы свойству значение Added, передайте в качестве второго аргумента False;

если необходимо задать значение передайте True, Метод LoadDataRow также возвращает только что созданный объект DataRow.

236 Часть III Автономная работа с данными: объект DataSet модели Метод возвращает для объекта новый объект но не добавляет его в набор Rows указанного объекта. Добавление в набор следует осу ществить вручную, предварительно заполнив необходимые поля объекта DataRow.

Так каким же из этих трех методов воспользоваться?

Х Для импорта записи из стороннего объекта DataTable используйте метод Row.

Х Для одновременного импорта нескольких записей, например на основе содер жимого файла, применяйте метод Это позволит вам писать меньше кода, чем при работе с методом NewRow.

Х Во всех остальных случаях метод NewRow.

Метод Reset Метод Reset восстанавливает оригинальное состояние объекта DataTable. в кото ром он находился до инициализации. Чтобы отбросить имеющийся и начать боту с новым объектом DataTable. используйте метод Reset, а не создавайте новый экземпляр DataTable.

Метод Select Метод Select позволяет искать записи в объекте DataTable на основе разнообраз ных критериев поиска. Он возвращает массив объектов DataRow, щих заданным критериям.

Подробнее о методе Select Ч в главе 8.

События объекта В табл. 6-10 перечислены наиболее часто используемые события DataTable.

Таблица 6-10. События объекта DataTable Событие Описание Наступает после изменения содержимого поля Наступает перед изменением содержимого поля Наступает после изменения содержимого записи Наступает перед изменением содержимого записи Наступает после записи Наступает перед удалением записи События и События ColumnCbanged и ColumnCbanging наступают каждый раз, когда изменя ется содержимое одного из полей записи. Они позволяют осуществлять провер ку данных, активировать и элементы управления, и т.д.

У данных событий есть аргумент типа обладаю щий свойствами Row и Column, которые позволяют определить, какие именно поле и запись изменены.

Помните: при использовании данных событий для редактирования содержи мого записи иногда возникает цикл.

ГЛАВА 6 Работа с объектами DataSet События RowChanged и События RowChanged и наступают каждый раз, когда изменяется содержимое объекта или значение свойства этого объекта.

Чтобы определить, почему наступило событие, достаточно просмотреть зна чение Action аргумента этого Свой ство Row указанного аргумента позволяет обращаться к изменяемой записи.

События и События и RowDeleting предоставляют такие же аргументы и свойства, как события RowChanged и RowChanging. Единственное отличие в том, что данные события наступают при удалении записи из объекта DataTable.

Свойства объекта В табл. перечислены наиболее часто используемые свойства объекта Column.

Таблица Свойства объекта DataColumn Свойство Тип данных Описание Определяет, допустимы ли в столбце значения Boolean Null Boolean Определяет, ADO.NET для новые значения автоинкремента Определяет начальное значение автоинкремента Определяет шаг автоинкремента Integer Содержит заголовок столбца, отображаемый в Caption String связанных элементах управления Определяет, как ADO.NET запишет столбца в XML-документ Содержит имя объекта DataColumn String Type Определяет тип данных столбца Object Определяет значение по умолчанию, используе мое ADO.NET при заполнении этого поля в но вых записях Определяет, как ADO.NET генерирует значения Expression String основанных на выражении Содержит набор динамических свойств и значений Integer Задает максимально допустимую для столбца длину строки Содержит пространство имен, которое Namespace String использует при записи содержимого DataSet в XML-файл или при загрузке XML-данных в объект DataSet Ordinal Integer Возвращает порядковый номер объекта DataColumn в наборе Columns объекта DataTable Содержит префикс пространства имен, использу Prefix String емого ADO.NET при записи содержимого DataSet в XML-файл или при загрузке XML-данных в объект DataSet см. след. стр.

238 Часть III Автономная работа с данными: объект DataSet модели Таблица Свойство Тип данных Описание Boolean ли столбца только для чтения Table DataTable Возвращает объект в состав которого входит Unique Boolean ли быть данного уникальными в пределах DataTable Свойство Свойство AllowDBNull определяет, допустимы ли в объекте DataColumn значения Null. Значение по умолчанию этого свойства новых объектов DataColumn Ч True.

При создании новых объектов DataColumn с помощью метода свойству AllowDBNull не назначается значение True, даже если соответствующий столбец БД не допускает значений Null. Когда вы вызываете метод Fill, объект не выбирает из БД информацию схемы. Чтобы выбрать эту инфор мацию и применить ее к новым столбцам объекта DataTable, воспользуйтесь ме тодом Свойства и Эти свойства определяют, генерирует ли для столбца значения автоин кремента.

Если задать свойству значение ADO.NET станет генериро вать для столбца значения автоинкремента. Значение данного свойства по умол чанию Ч False. Как и в случае со свойством AllowDBNull, чтобы задать свойству объектов соответствующих столбцам БД с автоинкре ментом, значение True, используйте метод Если значение Autolncrement Ч True, ADO.NET генерирует новые зна чения автоинкремента на основе значений свойств Autolncre mentStep. Значение свойства AutolncrementSeed по умолчанию Ч 0. а AutolncrementStep Ч Как я уже объяснял, если вы генерируете новые значения автоинкремента средствами ADO.NET, указанным свойствам следует задать значение Вызов метода не влияет на значения свойств Autolncre mentSeed и AutolncrementStep.

В одном из предыдущих разделов рассказывалось, почему не стоит применять средства автоинкремента ADO.NET для генерации новых значений для БД. Пусть реальные значения автоинкремента генерирует БД, a ADO.NET генерирует значе ния-метки для объектов DataSet.

Свойство Caption Свойство Caption определяет заголовок отображаемый при со держимого объекта DataTable в связанном элементе управления По умол чанию Caption возвращает то же значение, что и свойство Тем не менее, если задать свойству Caption какое-либо значение, будет выводиться уже оно, а не значение свойства ColumnName.

ГЛАВА 6 Работа с объектами DataSet Свойство определяет, как сохраняет столб ца, возвращая данные объекта DataSet в XML-формате.

Данное свойство принимает значения из перечисления относя щегося к пространству имен Значение свойства по умолчанию Ч т. е. значения отдельных полей объекта представ лены тегами элементов. Свойству ColumnMapping можно задать значение Hidden или Далее чем отличается содержимого DataSet при по мощи элементов и атрибутов.

Используется = Используется = Customer" Contact" 555-1212" /> Подробнее о функциях для работы с XML-данными Ч в главе 12.

Свойство Свойство ColumnName содержит имя объекта Его в конструкторе DataColumn.

Свойство DataType Свойство DataType определяет тип данных, выбранный для содержимого столбца. По умолчанию данные столбцов хранятся в виде строк, Для хранения данных использует типы данных В моделях доступа к данным, например ADO, результаты запросов по своим типам данных соответствовали типам, применяемым в БД.

Так, в SQL Server предусмотрены разные типы данных для строк и фиксированной а также для строк в однобайтовом и двубайтовом пред ставлении. ADO обрабатывает все их по-разному. Если же говорить об объекте модели ADO.NET, строка Ч это просто строка.

Свойство DataType принимает значение типа Туре. Ниже как напря мую задать значение свойства DataType объекта DataColumn и использовать ме тод 240 Часть III Автономная работа с данными: объект DataSet модели Visual Basic Dim col As New = As New Visual C# col = new = DataTable tbl = new Свойство Свойство DefaultValue позволяет генерировать для полей новых объектов Data Column значения по умолчанию.

SQL Server определяет для столбцов таблиц значения по умолчанию. Тем не менее свойство DefaultValue объекта DataColumn ведет себя несколько иначе, чем ана логичная функция SQL Server.

Определяя значение по столбца SQL Server, вы указываете строку с выражением. SQL Server оценивает это выражение каждый раз, когда задает полю значение по умолчанию.

Свойство DefaultValue принимает статичное значение с универсальным типом данных Object. Предположим, вы имеете дело с размещения заказов. Мож но посредством свойства определить значение столбца по умолчанию. Однако оно статично. Завтра значение поля OrderDate будет таким же, как и сегодня.

Свойство DefaultValue удобно, но не предоставляет такой гибкости, как соот ветствующие средства SQL Server.

Свойство Expression Свойству Expression можно задать выражение, которое ADO.NET будет просмат ривать каждый раз при обращении к содержимому столбца. Если изменить зна чение данного свойства по умолчанию (пустая строка), свойству объек та DataColumn автоматически задается значение True.

Ниже показано, как задать значение свойства Expression объекта DataColumn, чтобы получить произведение значений столбцов Quantity и объекта DataTable. Кроме того, этот код добавляет в DataTable новый объект и выводит содержимое основанного на выражении столбца в окне консоли.

ГЛАВА 6 Работа с объектами DaiaSet Visual Basic Dim As New Details") Dim col As New = "Quantity * Dim As OataRow = = = = Visual C# DataTable tbl = new DataColumn col = new = "Quantity * UnitPrice" DataRow = = 1;

= 1;

= 6;

= 18;

Подробнее о том, как ссылаться в основанных на выражении столбцах на содержимое других объектов DataTable Ч в главе 7. Подробнее о в свойстве Expression функциях Ч в документации Свойство Свойство объекта DataColumn возвращает объект предназначенный для хранения разнообразных объектов.

Объекты DataSet. DataTable, и Constraint также предоставляют свой ство ExtendedProperties.

Подробнее о данном свойстве, включая пример кода, Ч в разделе этой посвященном свойству ExtendedProperties объекта DataSet.

Свойство Свойство MaxLength позволяет гарантировать, что пользователь не поместит в объект DataColumn строку большего размера, чем допускает БД.

242 Часть III Автономная работа с данными: объект DataSet модели Значение этого свойства по умолчанию т. е. ограничений на длину строк нет. Как и в случае со и вызов метода не влияет на значение Тем не менее его можно посредством метода Свойства Namespace и Prefix Свойства и Prefix позволяют для объекта DataSet префикс и пространство имен XML. использует значения свойств при записи содержимого в XML-файл, а при загрузке XML-документа в объект DataSet.

Объекты DataSet и также обладают свойствами Namespace и Prefix.

о пространствах имен Ч в документации Свойство Ordinal Свойство Ordinal возвращает порядковый номер объекта в наборе Columns объекта DataTable. Это свойство доступно только для чтения и, если DataColumn не относится к какому-либо DataTable, возвращает Свойство Свойство Readonly определяет, доступно ли содержимое столбца только для чте ния. данного свойства по умолчанию Ч False.

Если изменить значение по умолчанию свойства Expression объекта DataColumn (пустая строка), свойству Readonly автоматически задается значение True. При этом свойство Readonly становится доступным только для чтения.

При попытке изменить содержимое столбца, значение свойства Readonly ко торого Ч генерирует исключение Однако, даже если значение свойства Readonly Ч True, до добавления объекта в набор объекта DataTable содержимое столбца все равно можно изменять.

Как и в случае со свойствами AllowDbNull и на значение свой ства Readonly влияет только метод но не метод Fill объекта Свойство Table Свойство Table возвращает объект DataTable, в состав которого входит DataColumn.

Если последний не относится к набору Columns какого-либо объекта DataTable, данное свойство возвращает неинициализированный объект.

Свойство Unique Свойство Unique позволяет обеспечить уникальность значений столбца в преде лах объекта DataTable. Значение этого свойства по умолчанию Ч False, Если задать свойству Unique значение True, то для объекта DataTable, в состав которого входит DataColumn, создается объект UniqueConstraint. Аналогич когда вы добавляете объект UniqueConstraint, основанный на отдель ном свойству Unique соответствующего объекта DataColumn задается значение True.

Если определить ограничение на уникальность или первичный ключ на осно ве нескольких ADO.NET не задаст свойствам Unique всех соответствую щих объектов DataColumn значение поскольку значения в пределах столбца ГЛАВА 6 Работа с объектами DataSet не обязательно уникальные. Например, в таблице Order Details БД оп ределен первичный ключ на столбцов и Ни один из этих столбцов не содержит уникальных значений, поскольку запись о заказе может чать а один товар может быть включен в несколько заказов.

Как и в случае со свойствами и на значение ства Unique влияет только метод но не метод Fill объекта Свойства объекта В табл. перечислены наиболее часто используемые свойства объекта Таблица Свойства объекта DataRow Свойство Тип данных Описание Boolean Указывает, содержит ли текущая запись ошибки Object Возвращает/задает содержимое поля Массив типа Object содержимое записи сведения о наличии в записи ошибок Возвращает состояние записи Возвращает объект в состав которого вхо дит запись Свойство позволяет содержит ли объект DataRow ошибки.

Это свойство возвращает логическое значение и доступно только для чтения.

Свойство Item Свойство Item позволяет просматривать и изменять содержимое отдельного поля записи. Обращаться к содержимому поля допустимо по порядковому номеру или имени поля, а также с использованием объекта Кроме того, Item может принимать значение из перечисления определяющее, какую версию поля вы хотите видеть. Например, если вам потребуется оригинальное содержимое измененного поля, Свойство Свойство ItemArray позволяет просматривать и изменять значения всех полей записи. Это свойство принимает и возвращает массив типа элементы ко торого соответствуют столбцам объекта DataTable.

Если вы хотите с помощью свойства ItemArray изменить содержимое лишь отдельных полей записи, воспользуйтесь ключевым словом Nothing (Visual или null (Visual Следующий фрагмент кода пропускает первое поле за писи и изменяет содержимое второго, третьего и четвертого полей. Такой код потребуется вам при работе с объектами DataTable, включающими доступные только для чтения столбцы.

Visual Basic = New 2, 3, 4, 244 Часть III Автономная работа с данными: объект DataSet модели Visual C# = new object[] 2, 3, 4, Свойство Свойство RowError строку с информацией о содержащихся в записи ошибках. Если необходимо указать, что в записи есть ошибка, задайте свойству RowError строку соответствующего содержания.

объекта DataRow иногда возвращает True, даже если свой ству RowError задано пустое значение. Подробнее об этом Ч в документации Свойство Свойство RowState возвращает значение из перечисления указыва ющее текущее состояние записи. свойство доступно только для чтения.

Подробнее о возможных возвращаемых значениях свойства RowState пре дыдущих разделах этой главы.

Свойство Table Свойство Table возвращает объект в состав которого входит DataRow;

оно доступно только для чтения.

Иногда DataRow не относится к набору Rows какого-либо объекта DataTable например, когда он создан методом и еще не добавлен в набор Rows этого объекта DataTable. Тем не менее свойство Table всегда возвращает объект DataTable, в состав которого входит DataRow.

Методы объекта DataRow В табл. перечислены наиболее часто используемые методы объекта DataRow.

Таблица Методы объекта DataRow Метод Описание Подтверждает все отлаженные изменения в объекте DataRow BeginEdit редактирования содержимого DataRow Отменяет все сделанные после вызова метода BeginEdit Удаляет ошибки из объекта DataRow Delete Помечает объект DataRow как Подтверждает все сделанные после вызова метода BeginEdit GetCbildRows массив дочерних DataRow текущего объекта основываясь на объекте Получает сведения об в конкретном поле Возвращает для текущей записи массив объектов со держащих ошибки * Возвращает объект DataRow текущего объекта основываясь на объекте Возвращает массив родительских объектов DataRow текущего объекта основываясь на объекте ГЛАВА 6 Работа с объектами DataSet Таблица Метод Описание Возвращает логическое значение, указывающее, может ли объект вернуть требуемую версию данных Указывает, содержит ли определенное поле объекта DataRow чение Отменяет все отложенные изменения в объекте DataRow Задает сведения об ошибках в конкретном поле Изменяет родительский объект DataRow текущего объекта DataRow, основываясь на объекте Методы AcceptChanges и и RejectChanges позволяют подтверждать и отбрасывать все отложенные изменения в объекте DataRow.

По умолчанию, успешно передав отложенные изменения, хранящиеся в объекте объект DataAdapter неявно вызывает метод При этом свойству объекта DataRow задается значение Unmodified.

При вызове метода RejectChanges все отложенные изменения в объекте DataSet отбрасываются;

в этом случае свойству RowState объекта DataRow также задастся значение Предположим, у вас есть запись с информацией о клиенте, содержащая отло женные изменения. Поле изначально содержало значение Initial CompanyName, а теперь содержит значение New CompanyName.

После вызова метода AcceptChanges объект DataRow перестанет хранить ста рое оригинальное значение CompanyName. Если вы запросите текущее или оригинальное значение записи с помощью метода DataRow в лю бом случае вернет New CompanyName.

При вызове метода RejectChanges объект DataRow перестанет хранить новое значение New CompanyName. Если запросить текущее или оригинальное значе ние записи с помощью метода DataRow в любом случае вернет Initial CompanyName.

Подробнее о том, как использует оригинальные значения DataRow для передачи изменений в БД, Ч в главах 10 и Методы CancelEdit и Методы CancelEdit и EndEdit позволяют сохранять и отменять группы изменений содержимого объекта DataRow. Так, можно позволить пользователям редактировать содержимое записи и запросить подтверждение на сохранение или отмену этих изменений посредством диалогового окна.

Методы CancelEdit и EndEdit функционируют несколько иначе, чем методы и RejectCbanges. Проще всего объяснить разницу между этими ме тодами на примере. Следующий фрагмент создает новый объект изме няет его содержимое, вызывает метод BeginEdit, снова изменяет содержимое объекта DataRow и выводит различные версии содержимого записи.

246 Часть III Автономная работа с данными: объект DataSet модели Visual Basic Dim As New Dim As новую с row = Object() "Initial True) содержимое объекта вернет значение поля - "Initial CompanyName" = "New CompanyName" BeginEnit и снова содержимое поля CompanyName = "Even Newer различные версии содержимого & & _ rowC'CompanyName", & Visual C# tbl = new DataRow новую запись с помощью метода row = object[] "Initial содержимое объекта DataRow row.RowState вернет поля - "Initial CompanyName" = "New CompanyName":

BeginEnit и снова изменяем содержимое поля CompanyName = "Even Newer различные версии содержимого поля + ГЛАВА 6 Работа с объектами DataSel + ]);

Запустив код, вы увидите, что предполагаемое значение поля Ч Even Newer текущее значение Ч New и оригинальное Ч Initial CompanyName.

Для подтверждения редактирования можно использовать метод EndEdit.

значением поля станет предполагаемое значение. Оригинальное значение останется тем же.

Чтобы отметить вызовите метод Текущее и оригиналь ное значения поля неизменными.

Помните: если вы начали редактировать содержимое записи после вызова метода метод по умолчанию будет возвращать предпола гаемые значения полей. Подробнее о данной модели поведения Ч в разделе Про смотр отложенных изменений объекта этой главы.

Метод Метод ClearErrors удалить из объекта все ошибки. Он удаляет как сведения об ошибках в опъекте в целом, так и сведения об ошибках в отдельных полях записи.

Метод Delete При вызове метода Delete запись в действительности не удаляется из набора Rows соответствующего объекта Datalable. Вместо этого помечает запись как ожидающую удаления, чтобы ее можно было позже удалить из БД средствами метода Чтобы по-настоящему удалить объект вызовите его метод Delete и за тем Ч Для уменьшения объема кода стоит воспользоваться мето дом Метод Метод позволяет обращаться к дочерним записям текущего объекта DataRow и принимает объект или его имя. Можно также указать нужную вам версию содержимого дочерних записей, передав методу значе ние из перечисления DataRowVersion.

Метод GetChildRows возвращает дочерние данные в виде массива объектов Методы и Методы GetColumnError и SetColumnError позволяют просматривать и сведения об ошибках в конкретном поле. Они принимают имя поля, порядковый номер столбца в объекте или непосредственно объект Метод SetColumnError также позволяет удалить сведения об ошибках в конк ретном поле, передав в качестве второго параметра пустую строку.

248 Часть III Автономная работа с данными: DataSet модели Метод Если свойство объекта возвращает True, метод GetColumnslnError позволяет определить, какие именно поля объекта DataRow содержат ошибки.

Следующий фрагмент кода с помощью методов GetColumnslnError и возвращает информацию об ошибках для конкретного объекта DataRow.

Visual Basic Dim As DataRow If Then the following Dim As For Each colError In in & & & _ colError Else row does not contain errors") End If C# DataRow row;

if row contains the following + (DataColumn colError in in + + +, else row does not contain Методы GetParentRow, GetParentRows и Методы и позволяют просто и удобно просматривать и изменять запись текущего объекта DataRow в объек те Как и метод метод принимает объект DataRelation или его имя, а также значение из перечисления указывающее нужную вам версию содержимого родительской записи. Метод GetParentRows воз вращает объект DataRow.

Если у текущего объекта DataRow в отношении определено несколько роди тельских записей, для обращения к ним применяют метод который принимает те же параметры, что и GetParentRow, но возвращает массив DataRow.

ГЛАВА 6 Работа с DataSet Метод позволяет изменить определенную в отношении родитель скую запись объекта Ему достаточно передать новый родительский объект DataRow или его имя. Если текущий DataRow входит в состав объекта являющегося дочерней таблицей нескольких отношений, которые определены в объекте используйте перегруженный метод Он принимает в качестве второго параметра объект позволяя указать, на какое от ношение требуется сослаться.

Метод Has Version Как уже рассказывалось, объект DataRoiv хранит несколько версий данных Ч те кущую, оригинальную и предполагаемую. Тем не менее все версии данных одно временно не хранятся.

Например, если значение свойства RowState Ч Added, объект DataRow поддер живает только текущую, но не оригинальную версию данных. Объект значение свойства RowState которого Ч хранит только своего содержимого.

Метод позволяет определить, поддерживает ли объект нуж ную вам версию данных. Он принимает значение из перечисления и возвращает логическое значение, указывающее, содержит ли DataRow требуе мую версию данных.

Метод Предположим, у вас есть объект DataRow с информацией о клиенте и нужно получить содержимое поля в виде строковой переменной. Если для этого вы используете следующий код и поле ContactName содержит значение возможны проблемы:

Visual Basic Dim row As DataRow Dim As String = Visual DataRow string strContactName;

= (string) Во избежание этого стоит сконфигурировать БД и объект DataSet таким обра чтобы поле не допускало значений или проверять перед обращением к полю его содержимое на наличие значений null.

Метод значительно упрощает реализацию второго способа. Он прини мает имя поля, его порядковый номер или объект и возвращает логическое значение, указывающее, содержит ли поле значений null.

Предыдущий фрагмент кода можно изменить следующим Часть III Автономная работа с данными: объект DataSet модели Visual Basic Dim row As Dim strContactName As String If Then StrContactName = Else StrContactName = End If Visual row;

string strContactName;

if StrContactName = else strContactName = (string) Четвертый перегруженный метода принимает объект и из перечисления С этого метода IsNull уда ется определить, содержит ли конкретная версия поля значение null.

Свойства объекта В табл. перечислены наиболее часто используемые свойства объекта Unique Constraint.

Таблица 6-14. Свойства объекта UniqueConstraint Свойство Тип данных Описание Columns Массив объектов поля, на основе которых DataColumn определено ограничение String Возвращает имя ограничения Содержит набор динамических свойств и значений Boolean Указывает, является ли ограничение первичным ключом объекта DataTable Table Возвращает объект DataTable, на котором определено данное ограничение Свойство Columns Свойство Columns возвращает массив объектов DataColumn, содержащий столб цы, составляют ограничение. Это свойство доступно только для чтения.

Свойство ConstraintName Свойство ConstraintName позволяет просматривать и задавать имя объекта Unique Constraint.

ГЛАВА 6 Работа с объектами DataSet Свойство Свойство ExtendedProperties объекта возвращает объект Property для хранения разнообразных Объекты DataSet, и также предо ставляют свойство ExtendedProperties.

Подробнее о данном свойстве, включая пример кода, Ч в разделе этой посвященном свойству ExtendedProperties объекта DataSet.

Свойство IsPrimaryKey Свойство IsPrimaryKey возвращает логическое значение, указывающее, является ли объект UniqueConstraint первичным ключом объекта Это свойство доступно только для чтения. Сделать объект UniqueConstraint пер вичным ключом объекта DataTable удается только с помощью его конструкторов, Кроме того, чтобы определить первичный ключ объекта DataTable, следует воспользоваться свойством этого объекта.

Свойство Table Свойство Table возвращает объект в состав которого входит UniqueConst raint;

оно доступно только для чтения.

Свойства объекта ForeignKeyConstraint В табл. перечислены наиболее часто используемые свойства объекта KeyConstraint.

Таблица 6-15. Свойства объекта ForeignKeyConstraint Свойство Тип данных Описание AcceptRejectRule Определяет, каскадируются ли результаты ва методов и тельского объекта в дочерние записи Массив объектов Возвращает столбцы дочерней таблицы, DataColumn составляющие ограничение String Возвращает имя ограничения DeleteRule Rule Определяет, каскадируются ли удаление роди объекта в дочерние ExtendedProperties Содержит набор динамических свойств и значений Массив объектов Возвращает столбцы родительской DataColumn составляющие ограничение DataTable Возвращает родительскую таблицу ограничения Table DataTable Возвращает дочернюю таблицу ограничения UpdateRule Rule Управляет каскадированием изменений роди тельской записи в дочерние записи Свойства AcceptRejectRule, и Свойства AcceptRejectRule, DeleteRule u UpdateRule управляют порядком вания изменений родительской записи в дочерние записи.

252 Часть III работа с данными: объект DataSet модели принимает значение из одноименного перечисления, Значение этого свойства по умолчанию Ч т. е. вызов метода или RejectRule объекта не сказывается на дочерних записях последнего.

Если задать значение Cascade, изменения каскадируют ся в дочерние записи, определенные объектом Свойства и функционируют аналогичным но при нимают значения из перечисления Rule. Значение этих свойств по умолчанию Cascade, т. е. изменения родительской записи каскадируются в дочерние записи.

Например, при вызове метода Delete родительского объекта DataRow вы неяв но вызываете и метод Delete его дочерних записей. Точно так же, редактируя зна чение поля ключа родительского объекта DataRow, вы неявно изменяете содер жимое соответствующих полей дочерних записей.

Если каскадировать изменения не требуется, задайте свойствам и UpdateRule значение None. Можно также задать им значение или В первом случае при изменении или удалении содержимого родительской запи си соответствующим полям дочерних записей задаются значения null, а во вто ром Ч их значения по Свойства Columns и Свойство Columns возвращает массив объектов содержащий столб цы дочерней таблицы, которые составляют ограничение. Свойство возвращает аналогичные столбцы родительской таблицы.

Оба свойства доступны только для чтения.

Свойство Свойство позволяет просматривать и задавать имя объекта Foreign Свойство Свойство ExtendedProperties объекта возвращает объект предназначенный для хранения разнообразных объектов.

Объекты DataColumn, и также предостав ляют свойство Подробнее о данном свойстве, включая пример кода, Ч в разделе этой посвященном свойству ExtendedProperties DataSet.

Свойства и Table Свойство RelatedTable возвращает а свойство Table Ч дочерний объекта DataTable ограничения. Оба свойства доступны только для чтения.

Вопросы, которые стоит задавать почаще Вопрос. Стоит ли использовать объект DataSet при работе лишь с несколькими данных?

Ответ. В этой ситуации можно просто воспользоваться объектом DataTable, не прибегая к помощи объекта DataSet. DataSet предоставляет поддержку отношений ГЛАВА 6 Работа с объектами DataSet между таблицами, возможность чтения и записи в файлы и потоки, а так же поддержку XML-функций. Если все это вам не нужно, воспользуйтесь объек том Вопрос. Я добавил в объект DataTable новую запись, и при передаче этой запи си в БД возникла ошибка, связанная с что запись нарушает определенное на таблице ограничение Почему такой ошибки не при добавлении записи в Ответ. обеспечивает соблюдение создаваемых вами ограничений, ос новываясь на данных объекта DataSet. Созданная вами новая запись нарушит оп ределенное на таблице ограничение только если в объекте DataTable уже есть запись с такими же значениями полей первичного ключа. В нет каких-либо наследуемых знаний о содержимом вашей БД, Вопрос. Как просмотреть содержимое удаленной записи?

Ответ. Передайте в качестве необязательного параметра свойства Item констан Вопрос. Можно ли отменить изменения, внесенные мной в записи?

Ответ. Да. Метод объектов DataTable и DataSet позволяет отменить все отложенные изменения затронутых записей, Вопрос. Как узнать, определен ли в объекте DataTable первичный ключ?

Ответ. Воспользуйтесь следующим фрагментом кода:

Visual Basic > DataTable есть ключ Else DataTable нет первичного ключа End If Visual C# > 0) DataTable есть первичный ключ else DataTable нет первичного ключа Вопрос. Что насчет объектов DataSet и метода Ответ. Объекты DataSet, DataTable и являются производными от класса предоставляющего метод Dispose и событие Disposed.

Метод Dispose позволяет освободить занимаемые объектом ресурсы. Если вам требуется выполнять код одновременно выполнением метода Dispose объекта, перехватывайте событие Disposed этого объекта, 254 Часть III Автономная работа с данными: объект DataSet модели Для тех, кто собирается вызывать метод Dispose какого-либо из вышеперечис ленных объектов, отмечу, что действие этого метода не При вызове метода Dispose объекта DataSet не осуществляется неявного вызова метода Dispose объектов из состава DataSet.

Работа с реляционными данными 1 БД редко бывают независимыми структурами данных. Из рис. 7-1 вид но, что все таблицы БД поставляемой с SQL Server 2000, взаимосвяза ны, и таблиц, стоящих особняком, нет.

Далеко не во всех БД процент взаимосвязанных таблиц так высок, но все же в большинстве БД взаимосвязанные таблицы есть. При разработке приложений вы обязательно столкнетесь с ситуацией, когда потребуется вывести или программ но обратиться к данным из связанных таблиц вашей БД.

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

Пользователи хотят удобно перемещаться между различными таблицами с информацией, занимаясь поиском связанных записей, например заказов конкрет ного клиента. Кроме необходима проверка данных, гаранти ровать, что в БД нет лосиротевших рядов. Приложениям зачастую приходится собирать агрегатные сведения, например для вывода общей стоимости и числа в заказе. Кроме того, при изменении родительской записи иногда требу ется каскадировать изменения в дочерние записи: скажем, если удален заказ, сто ит также удалить и связанные с ним товары.

В этой главе рассказывается о работе с данными из связанных объектов Table при помощи объекта Я также подробно опишу осо бенности объекта о которых упоминал в предыдущей главе.

Часть Автономная работа с данными: объект DataSet модели ~ Г Ч ~ ХХ. :

IP J Ч....

Рис. 7-1. Отношения между таблицами БД Особенности доступа к реляционным данным Вполне очевидно, что модель не является пионером в области доступа к реляционным данным. Ей предшествовали другие способы данных из связанных таблиц. Сейчас я познакомлю вас с основными способами работы с данными из связанных таблиц и вкратце сравню их с методом, когда использует ся объект Соединяющие запросы Соединяющие запросы предшествовали всем технологиям доступа к данным Micro soft. Этот простой, стандартный способ получить данные из несколь ких таблиц посредством одного запроса. Вот как запрос выбирает данные из таб лиц Orders и Order БД Northwind:

SELECT Customers C, Orders 0, [Order Details] D WHERE C.CustomerlD = 0. AND OrderlD = Преимущества соединяющих запросов таковы:

Х этот стандарт получил широкое признание. Все программисты БД умеют использовать соединяющие запросы;

Х они возвращают данные в виде одной структуры;

Х они легко фильтруют результаты. Если вам требуются сведения о клиен тах из конкретной страны, добавьте в запрос фильтр, и запрос вернет только нужные вам данные.

ГЛАВА 7 Работа с реляционными данными Однако не обошлось и без недостатков.

Соединяющие запросы иногда возвращают избыточные данные. Если клиент разместил 100 заказов, для каждого из них будет возвращена инфор мация об этом клиенте (рис. 7-2).

. ХХ.

.. :..,,.

Е.5) ч..

.5) 5) (Б] ЕЕЕ- Ana (Б] 555-472S (5) 555- (5) (5).5) (5) 555- [5) 555. [5] [5] Рис. 7-2. Данные, возвращаемые соединяющим запросом Х Обновление результатов соединяющих запросов затруднено. Модели доступа к данным, например трудно определить, как же интерпре тировать изменения в результатах соединяющего запроса. Например, когда вы удаляете запись, означает ли это, что нужно удалить только соответствующую запись в дочерней таблице, или требуется также удалить эту запись в родитель ских таблицах? Когда вы добавляете запись, ли это, что ее нужно добавить только в дочернюю таблицу, или необходимо также добавить эту запись в родительские таблицы?

Х Синхронизация результатов соединяющих запросов затруднена. Ког да вы изменяете родительскую запись (например, вы изменили контактное имя клиента), обновленные данные требуется передать в БД и затем повторно полнить запрос, чтобы изменение проявилось также во всех запи сях набора результатов.

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

Преимущества отдельных запросов таковы:

258 Часть III Автономная работа с данными: объект DataSet модели Х в целом они возвращают меньше данных, чем соединяющие запросы;

Х они больше подходят для обновления результатов. Поскольку вы изме няете структуру (например, объект соответствующую отдельной технология типа ADO легко интерпретирует изменения и соответству ющим образом модифицирует БД;

Х отдельные запросы позволяют обращаться к разным источникам дан ных. Если связанные таблицы относятся к различным СУБД, данная возмож вам пригодится.

Недостатки отдельных запросов;

Х отдельные запросы требуют синхронизирующего кода. Чтобы найти заказы, размещенные конкретным клиентом, следует определить фильтр для дочернего объекта и написать код, синхронизирующий объекты Recordset друг с другом;

Х фильтрация результатов отдельных запросов затруднена. Создание за просов к дочерним таблицам, которые возвращают только записи, связанные с записями, полученными из родительской таблицы, Ч в общем-то, проблема тично. Подробнее об этом Ч в следующих разделах главы.

объекты Recordset ADO В ADO 2.0 реализована концепция объектов Recordset. Специальный поставщик данных и специальный синтаксис запроса позволили объединять нескольких запросов в одну структуру. Следующий фрагмент кода помеща ет содержимое таблиц Customers, Orders и Order Details в объект Dim rsCustomers As As Dim As Dim strConn As String, As String = & "Data & strSQL = "SHAPE CompanyName, & FROM AS Customers APPEND & _ CustomerlD, "FROM AS Orders APPEND OrderlD, & Quantity FROM [Order AS & "RELATE TO AS AS Orders & _ "RELATE TO AS Orders" Set rsCustomers = New strSQL, strConn, adOpenStatic, Set rsOrders = Set rsOrderDetails = У объекта Recordset есть три объектных переменных, однако все они ссыла ются на данные, хранящиеся в одной структуре. Когда вы перемещаетесь по объекту Recordset верхнего дочерних объектах Recordset доступны только свя занные данные.

ГЛАВА 7 Работа с реляционными данными Преимущества иерархичных объектов Recordset таковы:

Х они возвращают данных, чем соединяющие запросы;

Х они возвращают данные в виде одной структуры;

Х они годятся для простых обновлений. Несмотря на то, что объекты хорошо справляются с простыми обновлениями, у них есть определенные ограничения. Б лучшем случае проблемы возникают при пере даче отложенных изменений нескольких таблиц.

У иерархичных объектов Recordset есть и недостатки:

Х синтаксис запросов ужасен. Посмотрите-ка на этот запрос! Хоть я и счи таю себя экспертом по ADO, я никогда и не думал изучать синтаксис SHAPE;

Х ограничены возможности управления. В запросе нужно отно шение;

Х можно обращаться только к одному источнику данных;

Х затруднена фильтрация.

Объекты модели Структура объектов DataRelation сильно отличается от структуры иерар хичных объектов Recordset. Объектам DataRelation не требуется дополнительный поставщик или отвратительный синтаксис запросов SHAPE. Объекты DataRelation считаются частью схемы объекта DataSet.

Если вкратце, объект DataRelation объединяет в себе преимущества отдельных запросов и иерархичных объектов Recordset в плане управления данными из свя занных таблиц и исключает практически все их недостатки. Приведенные ниже списки за и еще больше разожгут ваш интерес к объекту DataRelation.

Преимущества объектов DataRelation таковы:

Х они возвращают меньше данных, чем соединяющие запросы;

Х упрощают поиск связанных данных;

Х не требуют сложного синхронизирующего кода;

Х рассчитаны на сложные случаи обновления. Например, вы можете добав лять новых клиентов до добавления их заказов, а также удалять имеющиеся заказы перед удалением имеющихся клиентов. Также, если у вас есть группа отложенных изменений таблиц Orders и Order Details, перед передачей новых записей в таблицу Order Details можно выбрать для новых заказов автоинкре ментные значения, генерируемые сервером. Подробнее о таких ситуациях в главе Х они являются динамическими. Их можно программно создавать, изменять и удалять как до, так и после запроса к связанным таблицам БД;

Х поддерживают каскадные обновления. должны ли изменения родительской записи передаваться дочерним записям, можно при помощи свойств ограничения связанного с объектом Х позволяют создавать иерархии на основе разных источников данных.

Вам нужно связать результаты запроса о клиентах к БД SQL Server и результа ты запроса о заказах к БД Oracle? Без проблем.

260 Часть Автономная работа с данными: DataSet модели Недостаток у объектов только один:

Х затруднена фильтрация. К сожалению, объекты DataRelation не позволяют легко выбрать только дочерние соответствующие нужным родительс ким записям. Подробнее о способах разрешения данной проблемы Ч далее в этой главе.

Работа с объектами DataRelation в коде Вы можете использовать собственный код для перемещения по нескольким таб лицам данных, для проверки и агрегации данных, а также для каскадирования изменений. Тем не менее эти же операции легко и просто осуществляются сред ствами объекта DataRelation модели ADO.NET. Сейчас я как программно создать объект DataRelation.

Создание объектов DataRelation У объекта DataRelation есть несколько важных значения которых зада ются с помощью конструкторов. При создании DataRelation следует ука зать его чтобы объект удалось в наборе;

кроме того, необходимо ука зать родительский и дочерний столбцы, на которых будет основано отношение.

Чтобы упростить создание одноименных объектов, класс DataRelation предостав ляет отдельные принимающие отдельные объекты и массивы таких объектов.

В стандартном примере, создающем отношение, используются объекты Data содержащие информацию о заказах и клиентах (рис. 7-3). Следующий фраг мент кода создает объект DataRelation для данного примера:

Basic новый DataSet и добавляем объекты DataTable и DataColumn Dim As New DataSet() объект DataRelation, связывающий две таблицы Dim As DataRelation = New Visual новый объект DataSet и добавляем объекты DataTable и DataColumn DataSet ds new объект DataRelation, связывающий две таблицы DataRelation = new ГЛАВА 7 Работа с реляционными данными - И/1 Я К In 9V с I/IS/I - - /4/ Рис. Вывод связанной информации Если нужно определить отношение, основанное на нескольких столбцах, вос пользуйтесь конструктором принимающим массивы объектов Column:

Visual Basic новый объект DataSet и добавляем объекты DataTable и ds As New DataSetC) массивы объектов DataColumn, на которых основан новый объект DataRelation Dim colsParent, As With colsParent = New _ End With With = New DataColumnO _ End With новый объект DataRelation Dim As = New colsParent, colsChild) Visual C# объект DataSet и DataTable и DataColumn DataSet ds = new DataSetO;

массивы объектов DataColumn, на которых основан новый объект DataRelation 262 Часть III Автономная работа с данными: объект модели DataTable tblParent = colsParent = new = colsChild = new новый объект DataRelation DataRelation = new colsParent, colsChild);

Кроме того, у DataRelation есть пара конструкторов, сигнатуры которых соот ветствуют сигнатурам, выше, и включают четвертый определяющий, нужно ли создавать для обеспечения ссылочной целостности на основе нового отношения. По умолчанию при создании объекта DataRelation в объекты DataTable добавляются ограничения (если только эти ог раничения еще не существуют). Подробнее об этом Ч чуть дальше.

Созданный объект DataRelation следует добавить в набор Relations объекта DataSet. Как и в случае с объектами DataTable создают и добавляют объект DataRelation в набор Relations объекта DataSet посредством од ного вызова:

Visual Basic новый объект DataSet и добавляем объекты DataTable и DataColumn Dim As New DataSet() объект связывающий две таблицы Visual C# новый объект DataSet и добавляем объекты DataTable и DataColumn DataSet ds = new объект DataRelation, таблицы Поиск связанных данных Одно из основных применений объекта DataRelation Ч поиск связанных данных в различных объектах DataTable. Тем не менее непосредственно объект DataRelation ГЛАВА 7 Работа с реляционными данными не предоставляет такой функциональности Ч она реализуется методами GetCbiid и объекта DataRow. Так каким же образом Relation участвует в таком поиске? Упомянутые методы принимают в качестве параметра объект DataRelation. Давайте подробно разберем, что представляют собой эти методы и как их использовать, Метод объекта Поиск связанных с родительской записью дочерних записей в другом объекте DataTable Ч очень простая задача. Для этого достаточно вызвать метод нужного объекта и передать ему имя объекта DataRelation, определяю щего отношение между объектами Вместо имени можно также пере дать сам объект DataRelation. Метод GetChildRows возвращает связанные данные в виде массива объектов Следующий фрагмент кода вызывает метод GetChildRows и просматривает воз вращаемые им данные;

Visual Basic о клиентах Din As DataRow Each rowCustomer In заказы, размешенные этими клиентами For Each In & Next rowOrder Next rowCustomer Visual C# записи о клиентах foreach (DataRow rowCustomer in { + - + размещенные этими клиентами foreach (DataRow rowOrder in + + - + rowO rde rde Метод объекта DataRow Объект позволяет перемещаться по не только вниз, но и вверх. У объекта есть метод GetParentRoiv, при помощи которого удается найти родительскую запись дочерней записи на основании определенного в объек те DataSet объекта DataRelation. Как и метод GetParentRow принимает нужный объект DataRelation или строку с его именем:

264 Часть III Автономная работа с данными: объект DataSet модели Visual Basic Dim rowOrder As записи о Each rowOrder In & vbTab & запись rowCustomer = & Next rowOrder Visual C# DataRow rowCustomer;

о (DataRow rowOrder in + + связанную запись rowCustomer = ' Метод DataRow Если вы имеете дело с отношением лодин ко и вам нужно просмотреть все родительские записи конкретного объекта воспользуйтесь методом объекта DataRow. Его сигнатуры аналогичны сигнатурам метода Visual Basic записи о клиентах Dim rowChild, rowParent As DataRow Each rowChild родительские For Each rowParent In Next rowParent Next rowChild Visual C# о клиентах foreach (DataRow rowChild in Rows) { с этими записями foreach (DataRow rowParent in + ГЛАВА 7 Работа с реляционными данными Примечание В БД редко встречаются отношения многие ко и далее я объясню почему.

Выбор версии данных для просмотра Представьте, что вы создали приложение, позволяющее получать из БД данные и изменять их. Однако пользователи этого приложения не слишком надежны и часто допускают ошибки. В связи с этим приложение использует функциональность объекта для записи изменений в файл, вместо того чтобы передавать их в БД (подробнее о данной возможности Ч в главе 12).

Как следствие, нужно создать второе приложение, которое позволит контро лерам просматривать отложенные сделанные пользователями первой программы. Это приложение для аудита будет отображать как оригинальные, так и конечные значения измененных записей объекта DataSet.

Из главы 6 вы помните, что метод Item объекта DataRow позволяет просмат ривать оригинальное и текущее значение конкретного поля соответствующей записи. Кроме методы и объекта DataRow принимают значение из перечисления указывающее нужную вам версию данных.

следующий фрагмент кода просматривает записи о клиентах и выводит оригинальные значения всех полей записей о заказах, размещенных конкретным клиентом:

Visual Basic записи о клиентах Dim As DataRow Each rowCustomer In & _ оригинальные значения записей о заказах, конкретным клиентом Each rowOrder In _ & Next rowOrder Next rowCustomer C# записи о (DataRow rowCustomer + - " + r оригинальные записей о конкретным клиентом foreach rowOrder in 266 Часть III Автономная работа с данными: DataSet модели + + !

Примечание не принимающие значения из перечисления выводят текущую данных, Проверка данных средствами объектов DataRelation Теперь, когда вы умеете с помощью объектов перемещаться по дан ным связанных объектов DataTable, мы рассмотрим еще одну важную объекта DataRelation Ч проверку данных.

При создании отношения между двумя объектами обычно требует ся гарантировать отсутствие в дочернем объекте DataTable дан ных, т. е. запретить пользователям добавлять в таблицу Orders записи, не соответ ствующие записям таблицы Customers. Объект DataRelation позволяет обеспечить соблюдение ограничений в объектах Создание ограничений По умолчанию при DataRelation в родительском объекте DataTable определяется ограничение а в дочернем объекте DataTable Ч ограни чение Constraint. Следующий фрагмент кода создает на столбце Custo объекта DataTable Customers ограничение а на столбце объекта DataTable Orders Ч ограничение Visual strConn, As String strConn = & "Initial Dim As New StrSQL = "SELECT CustomerlD, CompanyName, Customers" Dim As New strSQL = "SELECT CustomerlD, Orders" Dim daOrders As New Dim ds As New "Customers") "Orders") parent DataTable now contains & & ГЛАВА 7 Работа с реляционными данными " constraints") child DataTable now contains & constraints") Visual C# string strConn, strConn = + "Initial = = "SELECT CompanyName, ContactName FROM Customers";

= new strSQL = "SELECT CustomerlD, Orders";

OleDbDataAdapter daOrders new en);

DataSet ds = new parent DataTable now contains + Count + child DataTable now contains + Использование имеющихся ограничений Ограничения можно также определять заблаговременно;

новый объект воспользуется имеющимися ограничениями вместо того, чтобы создавать Visual Basic Dim ds As New "Customers") "Orders") cn.CloseO With New End With With _ 268 Часть III Автономная работа с данными: объект DataSet модели _ End With _ parent DataTable now contains & & constraints") child DataTable now contains & Visual C# DataSet ds = new DataTable = = new tbl = ds.

parent DataTable now contains + child DataTable now contains + Смотри-ка! Нет ограничений!

Как вы помните, при создании объекта DataRelation ADO.NET по умолчанию до бавляет в объект DataSet ограничения и сигнату ры которых соответствуют аналогичным сигнатурам нового объекта DataRelation.

Если в объекте эти ограничения уже есть, DataRelation станет ссылаться на них. В противном случае ADO.NET явно создаст новые ограничения.

ГЛАВА 7 Работа с реляционными данными Однако есть еще один вариант. В одном из посвященном конструк торам класса DataRelation, говорилось, что есть конструкторы, позволяющие запретить создавать ограничения для объекта DataRelation. Такие конструкторы полезны, если вам нужен объект DataRelation, но не требуются соответствующие ограничения в объекте Ограничения и значения Null Возможно, мне удастся аас удивить. Например, я не мог и предположить, что даже при наличии ограничения в БД и объекте вполне могут появиться лосиротевшие Вы мне не верите? Выполните к своей любимой БД. похожие запросы к БД при раз - работке приложений или изучении не рекомендуется).

Orders SET = NULL Запрос успешно и в таблице Orders появится не.

связанные с какой-либо записью таблицы Customers. Чтобы вернуть все на свои места:

UPDATE Orders SET IS NULL Убедиться, что на таблице Orders определено ограничение ForeignKey Constraint Y, можно, выполнив приведенный ниже запрос. Если в таблице Customers нет записи, значение поля которой Ч запрос завершится с ошибкой:

Orders SET CustomerlD = = хотя бы одно поле указанное в ограничении Foreign значение не проверяются на соответствие этому ограничению. Помните об этом, определяя схему БД и объекта DataSet.

Объекты ссылающиеся на себя Иногда родительская и дочерняя таблицы, участвующие в являются одним и тем же объектом. Возьмем таблицу Employees БД Northwind. В ней есть столбец с идентификатором сотрудника, а также столбец ReportsTo с идентификатором руководителя сотрудника. Кроме того, на столбце ReportsTo определено ограничение FOREIGN KEY, гарантирующее, что данный столбец при нимает только из столбца EmpIoyeelD.

Следующий фрагмент кода выбирает из таблицы Employees данные в объект DataSet и создает ссылающийся на себя объект Visual Basic As String = & _ "Initial StrSQL "SELECT EmpIoyeelD, ReportsTo, & + ', ' + AS FROM Employees" 270 Часть III Автономная работа с данными: объект DataSet модели Dim da As New 01eDbDataAdapter{strSQL, strConn) Dim As New Dim As DataTable = _ False) Visual C# string strConn, strConn = " + "Initial StrSQL = "SELECT ReportsTo, + + ' + AS Employees";

da = new 01eDbDataAdapter(strSQL, DataSet ds = new DataTable tbl = Создать Ч только половина дела. Наша настоящая цель Ч вывес ти древовидный список всех сотрудников (рис. 7-4). Обход иерархии для сотрудников по их руководителям с определенными особен но если вы никогда не писали рекурсивный код. В таком случае рекомендую вам изучить документацию языка по вашему выбору и найти там необходимую инфор поскольку вопросы рекурсии не вошли в эту книгу.

Рис. 7-4. Вывод содержимого Employees с использованием ссылающегося на себя объекта далее фрагмент кода просматривает содержимое объекта Data Table и выводит данные о руководителе наивысшего ранга. В таблице Employees ему соответствует значение поля ReportsTo Ч Подробнее о значениях NULL и ограничениях Constraint Ч во врезке Constraint и значения Обнаружив руководителя код выводит его непосредствен ных подчиненных, добавляя перед их именами символ затем Ч под ГЛАВА 7 Работа с реляционными данными чиненных этих подчиненных и так до тех пор, пока не останется имеющих кого-либо в подчинении.

Но достаточно объяснений Ч подать сюда код!

Visual Basic Dim As For Each row In If End If Next row Public Sub DisplayRow(DataRow Dim rowChild As DataRow Each rowChild in strlndent & vbTab) Next rowChild End Sub Visual C# foreach (DataRow row in if static votd row, string strlndent) { + foreach (DataRow in strlndent + Примечание Руководителю наивысшего ранга соответствует запись Employees, значение поля ReportsTo которой Ч Кроме того, мож но сделать так, чтобы сотрудник подчинялся сам себе. Если вы имеете дело с таблицей, в которой реализован аналогичный подход к щимся на себя отношениям, вам потребуется слегка фрагмент кода.

Отношения ко многим В БД встречаются преимущественно отношения лодин ко многим. Клиент может разместить несколько заказов, на несколько товаров каждый, а сотрудник может подчиняться нескольким начальникам. Есть также отношения ко однако определить их в БД несколько труднее. Чтобы почему это так.

рассмотрим таблицы authors и БД pubs SQL Server.

Часть III Автономная работа с данными: объект DataSet модели Предположим, что между данными этих таблиц существует отношение мно гие ко поскольку один автор мог написать несколько книг, а у одной книги может быть несколько авторов. Тем не менее эти две таблицы не связаны напря мую через ограничение поскольку это ограничение требует наличия уникального ключа. В связи с этим у дочерней записи не может быть несколько родительских записей в связанной таблице, т, е. здесь нет непосредствен ного отношения многие ко многим.

В БД pubs также есть таблица (рис. 7-5), позволяющая создать кос венное отношение многие ко многим. В данной таблице определен составной первичный ключ, включающий поля и title_id Ч поля первичного ключа таблиц authors и titles соответственно.

Рис. 7-5. Таблицы authors, и titleauthor БД SQL Предположим, что над одной из книг работали два В таблице titleauthor для такой книги будет две записи Ч по одной для каждого автора. Таким образом, таблица titleauthor позволит отыскать значения первичного ключа для всех авто ров конкретной книги. Точно так же выполняется поиск значения первичного ключа всех книг, которые автор написал самостоятельно или в работе над кото рыми принимал участие.

Следующий код получает данные из всех трех таблиц. Он добавляет объекты связывающие таблицу authors и titleauthor, а также таблицу и Далее код просматривает записи объекта authors, выводит имя автора и затем при помощи объектов DataRelation выводит написанные этим ав тором книги.

Visual Basic Dim strConn, as string = & ГЛАВА 7 Работа с реляционными данными "Initial Dim As New Dim daTitles, As = "SELECT FROM authors" daAuthors = New StrSQL = "SELECT title titles" daTitles = New strSQL = "SELECT titleauthor" daTitleAuthor = New 01eDbDataAdapter(strSQL, Dim ds As New "authors") "titles") "titleauthor") _ _ False) _ _ False) Dim As DataRow Each rowAuthor In & & For Each rowTitleAuthor In _ rowTitle = & Next rowTitleAuthor Next rowAuthor Visual C# string strConn, strSQL;

strConn = + "Initial = new cn.OpenO;

dsTitles, strSQL = "SELECT FROM authors";

daAuthors = new strSQL = "SELECT title FROM titles";

daTitles = new strSQL "SELECT titleauthor";

daTitleAuthor = new 274 Часть III Автономная работа с данными: объект DataSet модели DataSet = new false);

false);

{DataRow in { + + foreach (DataRow in { DataRow = + Использование объектов в объектах основанных на выражениях В главе 6 я рассказывал, как с помощью свойства объекта создавать объекты DataColumn, отображающие результаты уравнений типа Quantity ' Кроме того, основанные на выражениях объекты DataColumn можно использовать совместно с объектами DataRelation для вычисления агрегатных например числа дочерних записей, а также суммы и средних значений дочерних данных.

Далее показаны два примера использования объектов DataRelation в Expression объекта DataColumn. Сначала код создает отношение между объектами DataTabie Orders и Order Details, а затем добавляет в объект Order Details вычисляемый объект DataColumn ItemTotal. После этого код добавляет два осно ванных на выражениях объекта использующих новое отношение.

Первый объект DataColumn возвращает число дочерних записей. Чтобы полу чить его, код задает свойству объекта DataColumn следующее значение:

Данный синтаксис можно использовать для ссылки на дочерние данные, только если у объекта DataTabie есть единственный связанный дочерний ГЛАВА 7 Работа с реляционными данными объект Если дочерних объектов несколько, воспользуйтесь таким син таксисом:

Второй объект возвращает сумму значений объекта ItemTotal в дочернем объекте DataTable. Свойству Expression данного объекта DataColumn задается значение, похожее на значение одноименного свойства пер вого объекта DataColumn:

Visual Basic Dim As New "Quantity Visual C# DataSet ds = new "Quantity * Основанные на выражениях объекты DataColumn также позволяют получать информацию из участвующего отношении родительского объекта DataTable. В одном из предыдущих примеров мы рассматривали многие ко мно между таблицами author и БД pubs: фрагмент кода выводил список книг, которые автор написал сам или в работе над которыми принимал участие.

Можно упростить этот код, добавив в объект DataTable titleauthor основанный на выражении объект DataColumn, который использует отношение между объек тами DataTable titleauthor и title и возвращает значение объекта DataColumn title.

После этого нам не искать требуемую запись в объекте DataTable с помощью 276 Часть III Автономная работа с данными: объект DataSet модели Visual Basic Dim ds As New DataSetO _ _ _ False) _ Dim As Each rowAuthor In & A For Each rowTitleAuthor In & Next rowTitleAuthor Next rowAuthor Visual C# DataSet ds = new DataSetO;

false);

(DataRow rowAuthor in + + foreach (DataRow rowTitleAuthor in ГЛАВА 7 Работа с реляционными данными + Полный агрегатных функций для свойства Expression Ч в документа ции Каскадирование изменений Иногда изменения содержимого записи должны отражаться на связанных дан ных. удалив заказ, вы, возможно, захотите удалить и входившие в него товары.

Различные СУБД по-разному данную ситуацию. Ограничение FOREIGN KEY в таблице Order Details БД SQL Server гарантирует, что пользователь не сможет удалить из таблицы Orders запись, связанную с записями таблицы Order Details. В SQL Server 2000 реализована поддержка каскадных изме нений на основе ограничения FOREIGN KEY. Определяя ограничения FOREIGN KEY вы можете быть уверены, что при обновлении или удалении записи изменения автоматически каскадируются в записи связанной таблицы. На рис. 7-6 показа но диалоговое окно SQL Server 2000 для настройки параметров ограничения FOREIGN KEY.

relationship - Fields Рис. 7-6. Настройка параметров каскадирования для ограничения KEY в SQL Server Объект модели ADO.NET обладает аналогичными возмож ностями. Он предоставляет свойства DeleteRule и определяющие, что произойдет при изменении данных записи родительской таблицы, на которой определено ограничение FOREIGN KEY.

Свойства DeleteRule и объекта ForeignKeyConstraint Свойства DeleteRule и UpdateRule принимают значения из перечисления Rule, от носящегося к пространству имен Значение обоих этих свойств по умолчанию Ч Cascade, т. е. при удалении записи родительского объекта 278 Часть III Автономная работа с данными: объект DataSet модели также удаляются дочерние записи связанного объекта Если измените значение поля в родительском объекте DataTable, на котором определено огра ничение FOREIGN KEY измените значение поля объекта Customers), это значение также обновится и в связанных записях до чернего объекта DataTable, Другие возможные значения свойств DeleteRule и Ч и Если значение свойства Ч None, связанные данные из дочер него объекта DataTable не удаляются. Если нужно изменить родительскую запись и задать одному из задействованных в ограничении полей значение NULL, задай те свойству DeleteRule и/или свойству UpdateRule значение NULL. Точно так же, если задать этим свойствам значение полям дочерней записи, задействован ным в ограничении FOREIGN KEY, будет задано значение свойства Default.

Постепенный отказ от соединяющих запросов Многие разработчики получают данные из нескольких таблиц при помощи со запросов. вы имеете право поместить результаты запроса, возвращающего данные нескольких таблиц, в объект DataTable, но обычно я не рекомендую этот способ. Как рассказывается в главе 10, объект пред назначен для просмотра изменений, хранящихся в отдельном объекте DataTable и передачи их в конкретную таблицу вашей БД. Таким образом, для изменения содержимого объектов DataTable данные следует поместить в отдельные объекты DataTable, соответствующие таблицам БД.

И что же нам делать с соединяющими запросами?

решение Ч разделить их на запросы, возвращающие данные от дельных таблиц. Тем не менее чаще легче это сказать, чем сделать. В приводив шихся фрагментах кода я использовал очень простые запросы, возвращающие все записи таблицы. Когда вы имеете дело с запросом, фильтр, ситуа ция усложняется:

SELECT Phone Customers WHERE Country = Если вам нужны только данные из связанной таблицы Orders, следует получить только сведения о которые разместили этим запросом кли енты. Поскольку в таблице Orders нет столбца Country, придется воспользоваться запросом, ссылающимся на таблицу Customers:

SELECT 0. ID, FROM C, Orders WHERE = AND = ГЛАВА 7 Работа с реляционными данными Создание объектов в Visual Studio Обсудив основные возможности объектов DataRelation, давайте разберем, как создавать их в Visual Studio Добавление объекта DataRelation в объект DataSet со строгим контролем типов В главе 6 я рассказал, как создавать объекты DataSet со строгим контролем типов средствами Visual просмотреть структуру объекта DataSet в конструкторе XML Schema Designer, дважды щелкните файл проекта DataSet в окне Solution Explorer.

Щелкните объект DataTable, который станет в отношении родительским, пра вой кнопкой и Relation (рис. 7-7). Можно также воспользоваться меню Schema среды Visual Studio Откроется диалоговое окно (рис. 7-8). по добавить новый объект DataRelation.

*, Рис, 7-7. Открытие диалогового Edit Relation В диалоговом окне Edit Relation для объекта задают дочерние и родительские объекты DataTable и Кроме здесь можно задать значения свойств ограничения связанного с новым объектом DataRelation. Если необходимо создать только ограничение и новый объект DataRelation не ется, пометьте флажок Foreign Key Only.

Щелкните ОК. В конструкторе XML Schema Designer появится графическое представление нового объекта DataRelation Ч соединяющая два объекта DataTable (рис. 7-9).

280 Часть III Автономная работа с данными: DataSet модели в toy a Рис. 7-8. Добавление нового объекта в диалоговом окне Edit Relation в в fe Х * X Х ftOdsrint ttrmg F.

fl-jng * [ f.

" Рис. Новый объект DataRelation Добавление объекта DataRelation в объект DataSet без типов Объекты DataRelation разрешается также добавлять в объекты DataSet без конт роля типов. В предыдущей главе рассказывалось, как добавить объект DataSet без контроля типов в область например на и затем до ГЛАВА 7 Работа с реляционными данными в него объекты и Добавить новый объект DataRelation же просто.

Выберите объект DataSet в панели компонентов области проектирования и затем выберите свойство в окне Properties. В правой части строки свойства появится кнопка для запуска мастера Relations Editor (рис. 7-10).

В, " '.' j Рис. 7-10. Добавление нового объекта DataRelation в объект без контроля типов при помощи мастера Relations Collection Editor Мастер Relations Collection Editor позволяет добавлять, редактировать и удалять объекты DataRelation. При добавлении нового или редактировании имеющегося объекта DataRelation открывается диалоговое окно Edit Relation (рис. 7-8).

Особенности объекта DataRelation Если справочная информация по объекту DataRelation не особенно инте ресна. Объект не предоставляет методов и событий, он обладает свойствами. Тем не менее не рассказать о них означало бы обмануть чьи-то ожи дания.

Свойства объекта Большинство свойств объекта DataRelation доступно только для чтения. Задать их значение можно средствами конструкторов объекта DataRelation. В табл. 7-1 пе речислены наиболее часто используемые свойства объекта DataRelation.

Свойство возвращает массив, содержащий объекты DataColumn из участвующего в отношении дочернего объекта DataTable. Данное свойство доступно только для чтения.

282 Часть III работа с данными: объект DataSet модели Таблица 7-1. Наиболее часто используемые свойства объекта DataRelation Свойство Тип данных Описание Массив объектов Указывает дочерние столбцы, определяющие Доступно только для чтения ограничение FOREIGN KEY в уча ствующей в отношении дочерней таблице, Доступно для чтения DataTable дочернюю таблицу в отношении.

Доступно только для чтения DataSet DataSet объект в котором нахо дится объект Доступно только для чтения ExtendedProperties набор динамических свойств Boolean нужно при до черние записи в дочерние объекты при за писи содержимого объекта DataSet в XML файл Массив Указывает родительские определяю DataColumn щие отношение. Доступно только для чтения Указывает ограничение UNIQUE в щей в родительской таблице. До ступно только для чтения DataTable Указывает родительскую таблицу в отноше нии. Доступно только для чтения String Указывает имя отношения Свойство Свойство ChildKeyConstraint возвращает ограничение на ко торое ссылается объект DataRelation. Если ваш объект DataRelation не использует ограничения, свойство ChildKeyConstraint возвращает Nothing или null, в зависимости от языка программирования. Данное доступно только для чтения.

Свойство Свойство ChildTable возвращает участвующий в отношении дочерний объект Data Table. Данное свойство доступно только для чтения.

Свойство DataSet Свойство DataSet возвращает объект DataSet, в находится объект Data Relation. Данное свойство доступно только для чтения.

Свойство ExtendedProperties Объект DataRelation, как и объекты DataSet, DataTable и DataColumn, предостав ляет свойство ExtendedProperties, позволяющее хранить дополнительную инфор мацию.

Свойство Nested Свойство Nested управляет содержимого дочернего объекта DataTable при записи содержимого объекта DataSet в с помощью метода ГЛАВА 7 Работа с реляционными данными Это одно из немногих свойств значение кото рого разрешается изменять.

Если значение свойства Nested Ч False (используется по умолчанию), данные дочернего и родительского объектов хранятся раздельно. Как показы вает следующий фрагмент кода, если предварительно не просмотреть информа цию схемы объекта не скажешь, что есть объект связываю щий оба объекта DataTable:

Данные дочернего и родительского DataTable хранятся раздельно Trujillo у При значении True вкладывает содержимое дочернего объекта Data Table в данные родительского объекта DataTable:

Данные дочернего объекта DataTable вложены в родительский объект Trujillo Emparedados у 284 Часть III Автономная работа с данными: DataSet модели <0rders> Свойство Свойство ParentColumns возвращает массив, содержащий объекты из участвующего в отношении родительского объекта Данное свойство доступно только для чтения, Свойство Свойство ParentKeyConstraint возвращает ограничение на кото рое ссылается объект DataRelation. Если ваш объект не свойство ParentKeyConstraint возвращает Nothing или null Ч в зависи мости от языка программирования. Данное свойство доступно только для чтения, Свойство Свойство ParentTable возвращает участвующий в отношении родительский объект DataTable. Данное свойство доступно только для чтения.

Свойство Свойство RelationName доступно как для чтения, так и для записи и позволяет получать и задавать имя объекта DataRelation.

Вопросы, которые стоит задавать почаще Вопрос. Когда нужно создавать объекты DataRelation без ограничений?

Ответ. Предположим, ваше приложение получает из БД данные о клиентах и заказах и выводит их в простой Web-форме. Приложение позволяет только про сматривать, но не редактировать информацию.

В таком приложении полезен объект DataRelation, с помощью которого легко вывести список заказов конкретного клиента. Однако ограничения в объекте DataSet скорее всего не понадобятся. Почему? Ограничения применяются для проверки данных, требующей времени. Если данные в приложении доступы только для чтения и БД уже проверила их средствами собственного набора ограничений, нет смысла повторно проверять эти данные.

Вопрос. Я собираюсь работать с данными нескольких но не буду выби рать все записи родительской таблицы. Приведенные в главе запросы, которые выбирают только связанные дочерние записи, кажутся мне сложными и неэффек ГЛАВА 7 Работа с реляционными данными Разве отдельный основанный на соединении запрос не будет в этой ситуации быстрее?

Ответ. В период тестирования бета-версии Microsoft,NET Framework в одной из групп новостей развернулось широкое да вопроса. Двое разра ботчиков пришли к выводу, что выборка данных от отдельных запросов неэффек тивна. Их предпосылки были логичными и разожгли мое и я решил проверить, как применение отдельных запросов влияет на производительность.

Я создал приложение на Visual Basic использующее ADO.NET, и приложение на Visual Basic, работающее с ADO 2.6. Оба приложения выбирали из таблиц Custo mers, Orders и Order Details БД информацию о клиентах, находящихся в США. Для каждого приложения я написал различные процедуры, получавшие данную информацию с использованием запросов разного типа.

Процедура, тестировавшая соединяющий просто выбирала данные в отдельный объект для которого не были ограничения. Я исполь зовал следующие запросы:

Запрос, основанный на соединении SELECT D.UnitPrlce FROM [Order Details] D, Orders 0, Customers С WHERE = O.OrderlD AND = C.CustomerlD AND = Отдельные запросы SELECT CompanyName, Phone Customers WHERE = SELECT FROM Orders 0, Customers С WHERE O.CustomerlD = C.CustomerlD AND = SELECT D.ProductID, [Order Details] D, Orders 0, Customers С WHERE D.OrderlD = O.OrderlD AND O.CustomerlD = C.CustomerlD AND = Параметризованные запросы SELECT CustomerlD, CompanyName, ContactName, Phone Customers WHERE = SELECT EmployeelD, OrderDate FROM Orders WHERE CustomerlD = ?

SELECT OrderlD, FROM Details] WHERE OrderlD = ?

286 Часть III Автономная работа с данными:

Как и многие другие участники группы новостей, я что производитель ность соединяющего и запросов окажется выше произво дительности отдельных запросов. К счастью, прежде чем поделиться своим мне нием с другими, я провел ряд тестов. Оказалось, что отдельные запросы работали быстрее всех. В среднем, их производительность были на 20% выше производи тельности соединяющего запроса и в 6-8 раз выше производительности парамет ризованных запросов.

Почему? оптимизация запросов Ч не самая сильная моя сторона, пола гаю, я все же смогу объяснить данный факт. Отдельные запросы вернули данные быстрее, чем один соединяющий запрос, поскольку последний возвращал боль ше данных. Соединяющий запрос возвращает избыточные данные, В таблице Order Details может оказаться 100 записей, соответствующих одной записи таблицы Customers, и каждая из них содержит одинаковую информацию.

Я воспользовался методом объекта (подробнее о нем Ч в гла ве 12) и записал содержимое объекта DataSet в XML-файл. Размер XML-файла, со ответствовавшего объекту DataSet с результатами соединяющего запроса, почти в три раза превышал размер XML-файла, соответствовавшего DataSet с ре зультатами отдельных запросов. Соединяющий запрос может показаться более эф фективным, потому что с ним проще работать, однако в действительности это не так, поскольку он возвращает больше данных.

Для тестирования параметризованных запросов я выполнил простой запрос к таблице Customers и поместил его результаты в объект Затем я стал просматривать эти результаты и единожды для каждого клиента выполнял пара метризованный запрос к таблице Orders. Далее я просматривал совмещенные результаты запросов к таблице Orders и единожды для каждого запроса выполнял параметризованный запрос к таблице Order Details. При этом пришлось вы полнять отдельные запросы для каждого клиента и каждого заказа. Структура па раметризованных запросов проста, однако их многократное выполнение для каж дого клиента и заказа оказалось неэффективным, и производительность Это не удар по параметризованным запросам. Просто они Ч не самое лучшее решение для выборки данных из больших иерархий с фильтрацией, похожих на те, которые я использовал в своем примере, Даже если вы работать с доступными только для чтения данными из нескольких таблиц, разделите соединяющие запросы на отдельные которые будут возвращать данные из отдельных таблиц.

Примечание Я также запускал две дополнительные процедуры, одна из кото рых применяла вложенные запросы IN, а другая объединяла отдельные запросы в пакет. Производительность запросов IN оказалась сравнима с производительностью процедуры, использовавшей отдель ные запросы. Объединив отдельные запросы пакет, я смог повысить производительность примерно на 8%.

Вопрос. Я выбираю данные из хранимых но, к сожалению, не могу использовать в них соединяющие запросы. Есть ли простой способ результаты на отдельные объекты ГЛАВА 7 Работа с реляционными данными Ответ. Осуществляющего это метода в модели нет Ч по крайней пока. Однако можно написать код, разделяющий результаты посредством объек та и метода Find набора Rows объекта (подробнее об этом методе Ч в следующей главе).

Следующий фрагмент кода выполняет соединяющий запрос к таблицам Custo mers и Order Затем он просматривает возвращаемые в объект данные и добавляет новые записи в отдельные объекты DataTable Customers и Orders.

Visual Basic Dim As String = & "Initial Dim As New strSQL = "SELECT & _ "FROM Customers C, Orders 0 & _ "WHERE = AND = Dim As New Dim rdr As OleDbDataReader = Dim As Object() Do While If Is Nothing Then = End If = New Object{) Loop Visual C# string strConn, strSQL;

StrConn = + "Initial 288 Часть Автономная работа с данными: объект DataSet модели = = "SELECT + Customers C, Orders 0 + "WHERE = AND = cmd = new rdr = cmd.

obj obj NewOrde while ( if null) < objNewCustomer = new object[] rdr.GetString{1), } = new object[] Сортировка, поиск, фильтрация главе 5 рассказывалось, как с помощью объекта DataAdapter выбрать резуль таты запроса в объект В главе б, посвященной объекту DataSet и его вло женным объектам, вы научились просматривать результаты таких запросов, пе ремещаясь по объектам объекта Но как найти запись в объекте DataTable по значению или группе зна чений? Как применить чтобы отображались только ющие заданному критерию? Как управлять порядком сортировки записей, к ко торым вы собираетесь обращаться или выводить пользователю?

Здесь даются ответы на все эти вопросы, а также обсуждается метод са метод Select класса DataTable и рассматриваются объекты и Возможности поиска и фильтрации объекта DataTable Объект DataTable предоставляет два метода для поиска данных по заданному кри терию. Первый Find, позволяет искать записи по значениям первичного ключа. Второй, выступает скорее в качестве фильтра, ряды дан ных, удовлетворяющие более гибким критериям поиска.

Поиск записи по значениям первичного ключа При запросах к БД часто требуется получить конкретную запись данных, осно вываясь на значениях ее полей первичного ключа и используя запрос, аналогич ный следующему:

290 Часть III работа с данными: объект модели SELECT CustomerlD, CompanyName, Phone FROM Customers WHERE CustomerlD = Объект тоже можно искать в объекте DataTable по значениям первич ного ключа записи. Вероятно, вы что последний фрагмент кода в гла ве 7 просматривал результаты запроса и должен был определить, есть ли опреде ленный ряд данных в объекте В том коде использовался метод Find для поиска в содержимом DataTable по значению первичного ключа.

Несмотря на то, что метод Find предназначен для объектов DataTable, его доставляет класс Метод Find принимает содержащий значение первичного ключа искомой записи. Поскольку значения первичного уникальны, метод Find вернет не более одного объекта DataRow. Следующий фраг мент кода ищет клиента по его значению первичного ключа и затем определяет, найдена ли запись.

Visual Basic Dim As String strConn = & _ "Initial strSQL = "SELECT Phone & _ Customers" Dim da As New strConn) Dim As New = New Dim row As DataRow = If Is Nothing Then not Else End If Visual C# string strConn, strSQL;

strConn = + "Initial strSQL "SELECT CustomerlD, CompanyName, ContactName, Phone + "FROM Customers";

OleDbDataAdapter da = new strConn);

DataTable tbl = new DataTableO;

= new DataRow row = if (row == null) not else ГЛАВА 8 Сортировка, поиск, фильтрация Примечание В принципе, объект может содержать несколько сей с одинаковыми значениями первичного ключа. Если задать свойству объекта значение False, при нарушении ничения PRIMARY KEY объект DataTable не будет генерировать чение. В результате метод Find все записи с искомым значением первичного Метод Find перегружен в расчете на случаи, когда первичный ключ вашего объекта DataTable состоит из нескольких объектов Например, пер вичный ключ таблицы Order Details основан на столбцах и Тогда для поиска записи в объекте DataTable с похожей схемой следует использовать такой код:

Visual Basic Dim strSQL As = & "Initial = "SELECT OrderlD, ProductlD, UnitPrice & "FROM [Order Dim da As New strConn) Dim As New DataTable(> = New Dim As New 28} Dim row As = If row Is Nothing Then not Else & - & End If Visual C# string strConn, strSQL;

strConn = + "Initial strSQL = "SELECT OrderlD, Quantity, UnitPrice " + [Order da = new strConn);

DataTable tbl = new = new objCriteria = new DataRow row = if == null) 292 Часть III Автономная работа с данными: DataSet модели not else + - + Динамичный поиск Поиск записи по значениям первичного ключа эффективен, но далеко не во всех ситуациях поиск окажется таким прямолинейным. Что, если требуется найти кли ентов из США (USA), живущих не в Сиэтле (Seattle)? Добавить такой критерий в запрос к БД можно при помощи раздела WHERE:

SELECT CustomerlD, Phone, City, Customers WHERE Country = AND City <> Метод Select объекта позволяет искать ряды по похожим критериям.

Предположим, вы выбрали все содержимое таблицы Customers в DataTable, Тогда для поиска клиентов из США. но не из Сиэтла, можно воспользоваться кри терием из приведенного выше запроса:

Visual Basic Dim strConn, As String = & "Initial strSQL = "SELECT CustomerlD, CompanyName, & _ "Phone, City, Country Customers" Dim da As New strConn) Dim As New Dim aRows As As DataRow aRows = = AND City <> For Each In aRows & & - & Next Visual C# string strConn, strSQL;

strConn = + "Initial strSQL = "SELECT CompanyName, ContactName, + "Phone, City, Country Customers";

da = new strConn);

DataTable tbl = new DataTableO;

DataRow[] aRows = = AND City (DataRow row in aRows) ГЛАВА 8 Сортировка, поиск, фильтрация + - + + - + Поиск по шаблону позволяет искать ряды по шаблону. Следующий SQL-запрос возвращает список клиентов, значение поля которых начинается с буквы Л.

SELECT CustomerlD, Phone FROM Customers WHERE CustomerlD LIKE В начало или конец строки поиска можно добавлять символы шаблона % и *.

этот запрос возвращает список клиентов из (New Hampshire), Нью-Джерси (New Jersey), (New Mexico) и Нью-Йорка (New York):

= "State LIKE Следующий запрос вернет список клиентов из Северной и Южной Дакоты (Dakota):

strFilter = "State LIKE Односимвольные шаблоны типа ? и _ в ADO.NET не допускаются.

Использование символов-разделителей Вы, возможно, заметили, что и в примере с запросом к БД, и в примере с методом указан критерий для столбцов со строковыми типами данных. В каждом случае мы заключали искомое значение в одиночные кавычки. Описание этого процесса кажется весьма простым, но вполне может создать трудности про граммистам.

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

LastName = Тем не менее, если в искомом значении уже присутствует символ-разделитель, его необходимо продублировать. В нашем случае критерий поиска будет таким:

LastName = Если вы создаете критерий поиска динамически, обязательно проверьте мое значение на наличие символов-разделителей. В этом случае вам пригодится метод Replace класса String. Следующий фрагмент кода создает строку поиска для метода Select и с помощью метода Replace класса String заменяет каждую одиноч ную кавычку в этой строке двумя такими кавычками:

Visual Basic = "LastName = &, ) & 294 Часть III Автономная работа с данными: объект DalaSet модели Visual strCriteria = = + ) + ;

А как указать в критерии поиска дату? Заключите ее в символы как показано ниже (к на символы-разделители датах можно не обращать внимания).

strCriteria = >= AND Иногда требуется заключить в имена столбцов, исполь зуемые в критерии поиска, Ч например, когда имя содержит пробел или другой символ, не к алфавитно-цифровым, или похоже на зарезервированное слово типа или SUM. если имя вашего столбца Ч Name и вам требуется выбрать все записи, значение поля Space In Name которых равно воспользуйтесь следующим критерием поиска:

strCriteria = In Name] = А что. если имя столбца включает символ-разделитель? Поставьте в критерии поиска перед закрывающим символом-разделителем символ если имя вашего столбца Ч и вам требуется выбрать все записи, значение поля которых равно 5, используйте такую строку поиска:

Visual Basic strCriteria = = 5" Visual C# strCriteria = = 5";

Примечание Помните, что в С* символ \ является управляющим. В предыду щем фрагменте кода мы фактически задаем переменной строку = 5" И прежде чем перейти от символов-разделителей к следующей теме, рассмотрим фрагмент который по-настоящему изящно справляется с ужас ной ситуацией. Объект DataTable в данном фрагменте кода содержит столбец с действительно некорректным именем, принимающий строки. Код выполняет поиск в этих строках, успешно заключая имя столбца и искомое значение в символы разделители.

Visual Basic Dim As New ГЛАВА 8 Сортировка, поиск, фильтрация As String Dim As strFieldName = strValue = strFilter = & & &, } & For Each In Next Visual DataTable tbl = new object[] true);

object[] true);

string strFilter, strFieldName, strValue;

strFieldName strValue = "O'Halley";

strFilter = + = + ) + ;

(DataRow in Примечание Полагаю, что прочитав два предыдущих абзаца, вы поняли: про стейший способ избежать проблем с символами-разделителями и заре зервированными словами в именах столбцов Ч не использовать их.

Использование дополнительных методов Select Как и многие методы объектной модели метод Select перегружен. Вы можете просто передать строку запроса, а можете и включить в нее порядок сор тировки, а также параметр, определяющий состояние искомых записей (напри мер, только добавленные записи или только измененные записи). Сейчас я вкратце расскажу об этих перегруженных методах.

Указание порядка сортировки В исходном фрагменте кода, использовавшем метод Select, мы искали в объекте DataTable с соответствующими данными информацию о клиентах из США, нахо дящихся вне Сиэтла. Управлять порядком объектов ме тодом можно посредством одной из сигнатур перегруженного метода.

В SQL-запросах порядок сортировки данных, возвращаемых запросом, задается в разделе ORDER BY. Так, следующий запрос возвращает список клиентов, отсор тированный по полю City:

296 Часть III Автономная работа с данными: объект DataSet модели SELECT ContactName, Phone, FROM Customers ORDER BY City Для сортировки по городам в порядке замените раздел BY City на ORDER BY City DESC.

Перегруженный метод как и раздел BY принимает порядок сортировки. Я изменил оригинальный фрагмент кода для сортировки объектов DataRow, возвращаемых методом Select, в убывающем порядке по полю City.

Visual Basic Dim As String & "Initial strSQL = "SELECT CompanyName, ContactName, & "Phone, City, Country FROM Customers" Dim da As New strConn) Dim As New Dim strCriteria As String = "Country = AND City Dim As String = "City DESC" Dim As = strSortOrder) Dim As DataRow For Each In aRows & - & 4 _ - & Visual C# strConn, strSQL;

strConn = + "Initial strSQL = "SELECT CustomerlD, ContactName, " + "Phone, City, Country FROM Customers";

OleDbDataAdapter da new strConn);

DataTable = new DataTableO;

string strCriteria = "Country = AND City <> string strSortOrder = "City DESC";

aRows = strSortOrder);

foreach (DataRow row in aRows) - + - + Указание нужного состояния искомых записей Как вы помните из главы б, объект DataSet поддерживает кэширование измене ний. Что, если надо выполнить поиск только в измененных рядах объекта ГЛАВА 8 Сортировка, поиск, фильтрация Воспользуйтесь перегруженным методом Select и укажите значение из перечис ления Можно считать, что это Ч фильтр, добавлен ный в критерий поиска. Предположим, вам требуется только изме ненные и удаленные записи объекта DataTable. Воспользуйтесь Modi и из перечисления DataViewRoivState и укажите в качестве па раметров фильтрации и сортировки пустые строки:

Visual Basic Dim As dvrs = Or Dim As = Dim As In aRows Next Visual C# DataViewRowState = | DataRow[] aRows = foreach (DataRow in aRows) Примечание Помните, что в случае с удаленными записями разрешается про сматривать только их Что представляет собой объект DataView Метод Select объекта DataTable Ч очень мощный и гибкий, но, тем не менее, не является оптимальным решением для всех ситуаций. У него есть два основных ограничения. Во-первых, метод Select принимает динамические критерии поиска и поэтому не может быть сверхэффективным. Во-вторых, Windows- и Web-фор мы не поддерживают связывание с возвращаемым метода Select Ч мас сивом объектов DataRow. В ADO.NET предусмотрено решение, обходящее оба этих ограничения, Ч объект DataView.

Объект модели ADO.NET в целом эквивалентен таблице БД, и поэто му можно предположить, что он аналогичен представлению БД. И хотя у объек тов DataView и представлений БД имеются общие черты, они не настолько похо жи друг на друга, как объекты и таблицы БД, * Объекты DataView возвращают данные из объектов У объекта нет собственной копии данных. При обращении через него к данным объект DataView возвращает данные, хранящиеся в объекте DataTable.

Представления БД ведут себя точно так же. При запросе к представлению БД возвращает данные из таблиц, на которые это представление ссылается.

298 Часть III Автономная работа с данными:

Объекты не являются Фактически представление БД Ч это запрос. Создавая в БД представление, вы указываете запрос, выполняемый БД для возврата данных представления:

CREATE VIEW AS SELECT C, Orders 0 WHERE = Объекты DataView модели фильтровать, сортировать и вести поиск в содержимом объектов DataTable, однако они не являются ми. С помощью объекта DataView нельзя объединить двух объектов Data равно как и просмотреть отдельные столбцы объекта Объекты DataView поддерживают фильтрацию на основе динамических но позволяют обращаться только к отдельному объекту кроме того, через объект DataView всегда доступны столбцы объекта DataTable.

соединений при помощи объекта Используя объект DataRelation и столбец, основанный на выражении, уда стся имитировать соединение, если у вас есть объекты с информацией о клиентах и заказах, можно между этими объектами и затем добавить объект DataTable с информацией о заказах на выражении объект чтобы отображать столбец из объекта DataTable с информацией о клиентах:

Basic tfs.Tab!es{"Orders").Columns.Add("CompanyName", _ Visual "Parent Использование объектов DataView в коде Объект DataView предоставляет функциональность, аналогичную возможностям метода Select объекта DataTable. Рассмотрим эту функциональность более подробно и попутно сравним ее с метода Select.

ГЛАВА 8 поиск, фильтрация Создание объектов Чтобы просмотреть с помощью объекта DataView данные объекта DataTable, его следует связать с этим объектом DataTable. Есть два способа указать объект Data используемый объектом DataView: посредством Table объекта Data View или конструктора этого объекта. Следующие фрагменты кода эквивалентны:

Visual Basic Dim As New Dim vue As DataView vue = New DataView() = tbl vue New DataView(tbl) Visual C# DataTable tbl = new DataView vue;

vue = new DataView();

= tbl;

vue = new DataView(tbl);

Примечание Если вы задаете свойству Table объекта значение Data измените значение по умолчанию свойства объекта Data Table (пустая Не почему, но конструктор объекта DataVieiv не проверяет объект DataTable на соответствие данному ограничению, У объекта DataView также есть которого более точно со Select объекта DataTable. Этот конструк тор задает значения свойств Table, и объекта в одной строке кода. Следующие фрагменты кода эквивалентны:

Visual Basic Dim tbl As New Dim As DataViewRowState = Dim vue As DataView vue = New DataView = tbl = "Country = = "City DESC" = vue = New DataView(tbl, "Country = "City DESC", 300 Часть Автономная работа с данными: объект DataSet модели Visual C# DataTable = new = DataView vue;

= new DataView;

= tbl;

= "Country = = "City = vue = new DataView(tbl, "Country = "City DESC", Использование свойства Свойство RowStateFilter принимает из перечисления (табл. 8-1). Это перечисление можно рассматривать как комбинацию свойства объекта и перечисления Свойство RowStateFilter работает в качестве двойного фильтра. Например, если задать ему значение ModifiedOriginal, через объект DataView окажутся доступны только измененные записи, и вы будете видеть их оригинальные значения.

Таблица 8-1. Элементы перечисления DataViewRowState Элемент Описание Added Отображаются записи Отображаются записи, которые не были удалены (значение по умолчанию) Отображаются удаленные записи Отображаются измененные записи с их текущими значениями ModifiedOriginal Отображаются измененные записи с их оригинальными значениями None Записи не отображаются Отображаются удаленные, измененные и не изменявшиеся записи с их оригинальными значениями Отображаются записи, которые не изменялись Использование объекта Если воспользоваться методом Select объекта DataTable к указать Modified метод вернет только измененные записи. Тем не менее, как видно из предыдущего фрагмента демонстрирующего работу метода в вызовах возвращаемых объектов по-прежнему требуется что нам нужны оригинальные значения полей записи, При использовании объекта DataView этот дополнительный этап не нужен, поскольку возвращает данные с собственного специализиро ванного объекта Ч DataRowView. Функциональность объекта DataRowView в це лом аналогична функциональности объекта DataRow. Кроме того, DataRowView ГЛАВА 8 Сортировка, поиск, фильтрация обладает свойством Item, обращаться к содержимому столбца как по имени, так и по порядковому номеру. И хотя свойство Item позволяет просмат ривать и изменять содержимое ряда, через объект доступна только одна версия данных записи Ч та, которая указана при помощи свойства этого объекта.

Следующий фрагмент кода посредством объекта DataView возвращает объект и при помощи объекта DataRowView просматривает содержимое записи:

Visual Basic Dim As New Dim vue = New Dim row As DataRowView = Visual C# DataTable tbl = new DataView vue;

vue = new DataRowView = Если объект DataRowView не обеспечивает требуемых возможностей, обрати тесь при помощи свойства Row этого объекта к соответствующему объекту Просмотр всех записей данных, доступных через объект DataView Доступ к данным объекта DataTable с помощью объекта DataView осуществляется иначе, чем непосредственный доступ к объекту DataTable. Объект DataTable пре доставляет свои записи данных через свойство позволяющее перемещаться по его содержимому при помощи цикла For Each. У объекта DataView нет похо жего, допускающего простое перечисление через который удавалось бы предоставлять данные.

Объект DataTable предоставляет свойство Count, возвращающее число записей, доступных через объект Используя это свойство, можно создать простой цикл For для просмотра всех записей.

Кроме того, объект DataTable обладает методом возвращающим объект Этот объект, относящийся к пространству имен System.Collec предоставляет функциональность перемещения по записям, аналогичную возможностям метода объекта Следующий фрагмент кода демонстрирует, как просмотреть содержимое объек та DataView с помощью свойства Count и метода GetEnumerator.

302 Часть III Автономная работа с данными: объект DataSet модели Visual Basic Dim As New данные в объект DataTable и изменяем несколько записей объект который только записи возвращает их исходное содержимое Dim vue As DataView vue = New Dim row As содержимое объекта DataView с помощью простого цикла Dim intCounter As Integer For intCounter = 0 To - row = Next intCounter содержимое DataView, используя метод Dim As = Do While = DataRowView) Loop Visual C# DataTable tbl = new данные в DataTable и изменяем несколько записей объект DataView, который содержит только измененные возвращает их исходное содержимое DataView vue;

vue = new DataView(tbl, DataRowView row;

содержимое объекта DataView с помощью простого цикла (int intCounter = 0;

intCounter < { = содержимое объекта DataView, метод GetEnumerator lEnumerator objEnum = while \ = !

ГЛАВА 8 поиск, фильтрация Поиск данных в объекте DataView Как вы уже знаете, свойства позволяют фильтровать в объекте DataView. Кроме того, объект DataView предоставляет методы Find и позволяющие искать в нем данные. Эти методы аналогичны методу набора Row объекта DataTable, Метод Find Задав значение свойства Sort объекта DataView, вы получите возможность с помо щью метода Find последнего искать ряды по столбцов, свойстве Sort. Как и в случае с методом Find объекта ному объекта DataView разрешено передавать одно или массив значений, Тем не менее метод Find объекта возвращает не объект или а значение типа integer, соответствующее порядковому номеру записи в объекте DataView. Если искомая запись не найдена, метод Find вернет -1.

Следующий фрагмент кода при помощи метода Find объекта ищет клиента по значению столбца Кроме того, код на основе возвраща емого значения метода определяет, нашел ли Find нужную запись.

Basic Dim As String & "Initial Dim As String = "SELECT ContactName, & "Phone, City, Country Customers" Dim da As New strConn) Dim As New Dim vue As New DataView(tbl) = "ContactName" Dim As Integer = Wilson") If intlndex = -1 Then not Else End If Visual C# string strConn = Data "Initial string strSQL = "SELECT CustomerlD, CompanyName, ContactName, "Phone, City, Country Customers";

da = new DataTable tbl = new DataView vue = new DataView(tbl);

vue.Sort = 304 Часть Автономная работа с данными: объект DataSet модели = if (intlndex -1) not else Метод FindRows Метод Find объекта осуществляет поиск по столбцам, перечис ленным в свойстве (первичный ключ) объекта Поскольку первичный ключ связан с ограничением UNIQUE KEY, по крайней мере одна за пись удовлетворит критериям поиска, переданным методу Find объекта DataRow Collection.

Метод Find объекта DataView осуществляет поиск по столбцам, указанным в Sort последнего. У многих записей могут быть одинаковые значения полей, используемых для сортировки данных объекте DataView. Например, при сорти ровке клиентов по полю Country для нескольких записей это поле может иметь значение Spain (Испания). Тем не менее найти посредством метода клиен тов из Испании нельзя, поскольку он возвращает только целочисленное значение.

К счастью, объект DataView также предоставляет метод FindRows. Его вызыва ют так же, как и метод Find объекта DataView, но метод FindRows возвращает мас сив объектов содержащих записи, которые удовлетворяют вашим критериям Следующий фрагмент кода проверяет, нашел ли метод FindRows записи:

Visual Basic vue As New DataView(tbl) = "Country" Dim aRows As = If = 0 Then rows Else Dim row As DataRowView Each row In aRows Next End If Visual C# DataView vue = new = "Country";

DataRowView[] aRows = if == 0) ГЛАВА 8 Сортировка, поиск, else in Модифицирование объектов DataRowView Ряд данных модифицируется с помощью объекта аналогично изме нению содержимого объекта Объект DataRowView, как и объект DataRow, предоставляет методы и Delete.

Создание новой данных при помощи объекта DataRowView несколько отличается от создания нового объекта DataRow. У объекта DataView есть метод возвращающий новый объект DataRowView. В действительности же но вая запись добавляется в базовый объект DataTable только при вызове метода EndEdit объекта DataRowView.

Ниже показано, как средствами объекта DataRowView изменить и уда ряд данных:

Visual Dim As New Dim vue As New новую запись Dim row As DataRowView = = = "New Company" = "New Contact" = 555-1212" запись rowC'CompanyName") = "Modified" запись Visual C# DataTable tbl = new DataView vue = new DataView(tbl);

запись DataRowView = = "ABCDE";

= Company";

= "New Contact";

= "(617) 555-1212";

Часть III Автономная работа с данными: объект DataSet модели запись запись Создание объектов в Visual Studio Создавать объекты проще, чем объекты DataTable. Вам не нуж но добавлять столбцы и типы Ч просто сошлитесь в объекте на и задайте нужные Sort и т.д.).

Добавление нового объекта DataView в конструктор Чтобы добавить новый объект DataView конструктор, перетащите элемент Data со вкладки Data панели инструментов Visual Studio в область проекти рования или на панель компонентов. Можно также дважды щелкнуть элемент DataView в панели инструментов.

Задание значений свойств объекта DataView После создания нового объекта DataView следует задать значения некоторых его свойств. Среда Visual Studio упрощает процесс. Б окне Properties (рис. достаточно выбрать доступный объект DataTable, а также задать значе ния других свойств объекта например и Sort.

X j Рис. 8-1. свойств объекта DataView в Visual Studio ГЛАВА 8 Сортировка, поиск, Вот, и все.

Особенности объекта DataView Изучив основные возможности объекта DataView, следует подробно рассмотреть его свойства и методы.

Свойства объекта В табл. 8-2 перечислены наиболее часто используемые свойства объекта DataView.

8-2. Свойства объекта DataView Свойство Тип данных Описание Boolean Указывает, допустимо ли удаление записей объекта AllowEdit Boolean допустимо ли записей объекта Boolean Указывает, ли добавление записей в объект DataView Boolean Указывает, используется ли порядок сортировки по умолчанию (первичный ключ) Count Integer Возвращает число записей в объекте (доступно только для чтения) Возвращает ссылку на контейнер объекта DataView только для Возвращает объект который заклю чает в себе запись данных, доступную через объект (доступно только для String Возвращает фильтр, указывающий, какие записи DataTable доступны через объект Data View. Аналогично разделу WHERE SQL-запроса Указывает, какие записи доступны через объект а также версию этих записей Sort String Указывает порядок сортировки доступ ных через объект DataView Table Возвращает объект с которым связан объект DataView Свойства и Объекты DataView нередко используются совместно со связанными элементами управления. При помощи свойств AllowEdit и удается легко какие действия пользователя допустимы в таких элементах ния. Вместо того чтобы задавать свойства отдельных связанных элементов управ ления, определите соответствующие свойства объекта DataView.

Значение по всех этих свойств Ч True, 308 Часть III Автономная работа с данными: объект DataSet модели Свойство Значение свойства ApplyDefaultSort по умолчанию Ч False. Если задать ему значе ние True, содержимое сортируется по первичному ключу объекта Data Table, связанного с объектом Кроме если вы измените значение свойства ApplyDefaultSort на свойству Sort объекта будут заданы стол бцы, составляющие первичный ключ объекта Например, если DataView связан с DataTable, который содержит информацию о заказах и первич ный ключ которого состоит из столбцов и то при задании свойству значения True свойству Sort объекта DataView неявно задается значение Свойства Count и Item Свойство Item параметризовано и возвращает объект Обращаясь к свойству передайте целое число, представляющее номер нужного вам ряда.

Свойство Count позволяет задать число рядов, доступных через объект DataView.

Следующий фрагмент кода просматривает содержимое объекта DataView с помо щью свойств Count и Item:

Visual Basic Dim As New данные в объект DataTable и изменяем несколько записей объект DataView, который содержит только записи возвращает их оригинальное содержимое Dim vue As DataView vue = New DataView(tbl) Dim As DataRowView помощью простого цикла содержимое DataView Dim As For intCounter = 0 To - = Next intCounter Visual C# DataTable tbl new данные в DataTable и изменяем несколько записей объект DataView, который содержит только записи возвращает их оригинальное содержимое DataView vue;

vue = new DataView(tbl);

DataRowView row;

помощью простого цикла просматриваем содержимое DataView (int intCounter = 0;

intCounter < intCounter++) ГЛАВА поиск, = Свойство DataViewManager Если объект создан с помощью метода CreateDataView экземпляра объекта свойство DataViewManager вернет объект со здавший ваш объект DataView. В противном случае возвращается неинициализи рованный объект DataViewManager.

Подробнее об объекте DataViewManager Ч в разделе Вопросы, которые стоит задавать этой главы.

Свойство Свойство RowFilter аналогично разделу WHERE SQL-запроса. Через представление доступны только удовлетворяющие заданному в свойстве критерию. Зна чение свойства RowFilter по умолчанию Ч пустая строка.

Простой фильтр на основе столбца со строками:

= "Country = Фильтр на основе шаблона (отображает только те ряды, значение поля которых начинается с Л):

= "CustomerlD LIKE Заключение дат в символы-разделители:

= AND < Заключение имен столбцов в символы-разделители и обработка в значении столбца:

= In Column Name] = Свойство Свойство RowStateFilter двумя способами определяет, какие данные доступны че рез объект DataView. Оно фильтрует объекты по значению их свойств а также определяет, какая версия ряда доступна через объект DataView.

Как уже свойство RowStateFilter принимает отдельные значения и их комбинации из перечисления Чтобы задать свойство применяют конструктор объекта DataView.

Значение свойства RowStateFilter по умолчанию Ч При этом через представление доступны все записи объекта удовлетворяющие кри терию, заданному в свойстве Sort объекта DataView, и не помеченные как уда ленные.

310 Часть Автономная работа с данными: DataSet модели Свойство Sort определяет порядок сортировки доступных через объект и функционирует практически аналогично разделу ORDER BY SQL-за проса. Порядок сортировки можно на отдельном поле или группе полей.

По умолчанию ряды сортируются в возрастающем порядке. Для сортировки по лей в убывающем порядке добавьте после имени поля ключевое слово DESC. Если имя поля содержит символ, отличный от (например, пробел), или является зарезервированным словом, не забудьте заключить его в символы разделители.

Простая сортировка по полям (Country, затем City):

= "Country, City" Сортировка в убывающем порядке:

vue.Sort = DESC" Заключение имени поля в символы-разделители:

vue.Sort = In Значение свойства Sort по умолчанию Ч пустая строка;

при этом все содержи мое объекта выводится в порядку базового объекта Задать свойство можно посредством конструктора объек та DataView, Свойство Table Свойство Table позволяет задать или обратиться к DataTable, с которым объект DataView. Если изменить свойства Table, свойствам и объекта задаются соответствующие значения по умол чанию.

Чтобы Задать свойство Table, используют конструктор объекта DataView.

На момент данной книги свойству Table не разрешалось задавать объект DataTable, которого Ч пустая строка;

в противном случае генерировалось исключение.

Методы объекта DataView Методы объекта DataView описаны в табл. 8-3.

Таблица 8-3. Методы объекта Метод Описание новый объект содержимого объекта DataView Копирует объекты в массив Помечает объект как удаленный внесение изменений объект DataView Find Выполняет в объекте DataView поиск отдельной ГЛАВА 8 Сортировка, поиск, фильтрация Метод Описание Выполняет в поиск нескольких записей данных объект для перечисления записей, через объект DataView Методы и Методы AddNew и позволяют добавлять и удалять записи данных из вого объекта Метод AddNew новый объект DataRowView. Задав значения нужных полей, можете вызвать метод объекта DataRowView и добавить запись данных в базовый объект DataTable.

Метод Delete принимает порядковый номер записи в объекте DataView и по зволяет удалить эту запись. Если у вас есть ссылка на объект или Data RowView, для удаления записи стоит применить метод Delete одного из этих объек тов. Помните, что в этом случае запись просто помечается как удаленная. Чтобы на самом деле удалить ее из объекта DataTable, вызовите (объек та DataTable или содержащего ряд) или передайте изменения в БД с помощью объекта Методы и Если вам необходимо изменить значения нескольких свойств объекта DataView, но вы не хотите, чтобы эти изменения сказались на доступных через этот объект данных, пока вы не измените значения всех нужных свойств, воспользуйтесь ме тодами Beginlnit и Представьте, что объект DataView связан с определенным объектом DataTable и значение свойства объекта DataView таково, что через по следний доступна лишь небольшая часть записей данных. Содержимое объекта DataView выводится в элементе управления Windows-форме, и по указа нию пользователя вам требуется изменять значения свойств Table и RowFilter та DataView. В данной ситуации изменяющий значения свойств объекта Data следует в вызовы методов Beginlnit и Endlnit объекта запретить элементе управления DataGrid моментально отображать все нового объекта DataTable, Метод То Объект DataView предоставляет метод То. Он функционирует методу СоруТо объекта и позволяет копировать объекты DataRowView, до ступные через объект DataView. в массив.

Примечание Возможно, разработчики, имеющие опыт работы с RDO и ADO, что метод СоруТо похож на метод возвращающий содержимое структуры данных в виде двухмерного массива. Увы, это не Если честно, я не знаю, чем вам поможет массив объектов DataRowView. Одна ко все же давайте рассмотрим фрагмент кода, в котором используется метод СоруТо, на если кто-то сумеет найти ему применение. Вероятно, этот человек вспом как помог ему данный фрагмент кода, и поблагодарит меня. Я принимаю и 312 Часть III Автономная работа с данными: объект DataSet модели Visual Dim As New Dim As vue = New As 0) Visual C# DataTable tbl new DataView vue;

vue = new aRows;

aRows = 0);

Методы Find и Методы Find и позволяют искать записи данных в объекте DataView. Они оба перегружены и принимают отдельное значение или массив значений. Объект DataView на основе указанных значений осуществляет поиск среди своего содер жимого по столбцам, перечисленным в свойстве Sort:

Visual Basic Dim strConn As String = & "Initial Dim As String = "SELECT & "Phone, City, Country FROM Customers" Dim da As New strConn) Dim tbl As New Dim vue As New DataView(tbl) the Find method to locate a & "based on the ContactName column") = "ContactName" Dim As Integer = Wilson") If intlndex = -1 Then & "Row not Else & End If the FindRows method to locate & "based on the Country column") = "Country" ГЛАВА 8 Сортировка, поиск, фильтрация Dim As = If = 0 Then & "No Else Dim As Each In aRows & row End If Visual string strConn = "Initial string = "SELECT "Phone, City, Country FROM Customers";

OleDbDataAdapter da = new strConn);

DataTable = new vue = new DataView(tbl);

the Find method to locate a "based on the ContactName = int intlndex = if (intlndex == -1) + "Row not + the FindRows method to locate rows + "based on the Country = "Country";

aRows = if == 0) "No rows else (DataRowView row in aRows) + Метод Метод GetEnumerator предоставляет один способ просмотреть содержимое объекта DataView. Он возвращает экземпляр объекта расположенно го в пространстве имен объекта lEnumerator аналогичен методу Read объекта и возвращает логическое значение, указывающее, доступен ли следующий объект набора. Свойство Current возвращает текущий объект с универсальным типом данных Object. Следующий фрагмент кода преобразует вывод в объект 314 Часть III Автономная работа с данными: объект DataSet модели Visual Basic Dim As New Dim vue As DataView(tbl) Dim As Dim As = Do While row = Loop Visual C# DataTable tbl = new vue = new DataRowView row;

lEnumerator = while t row = (DataRowView) Событие объекта DataView У объекта есть событие ListChanged, наступающее при изменении содер жимого объекта DataView, например при добавлении, удалении или изменении ряда данных, доступного через объект при заполнении объектом объекта DataTable;

при изменении значений свойств Sort или Table объекта DataView. Вот пример использования этого Visual Basic Dim vue As New Private Sub sender As Object, e As - & End Sub Visual C# наличие using DataView vue = new DataView;

+= new private void sender, ListChangedEventArgs e) ГЛАВА 8 Сортировка, поиск, фильтрация - + е.

Свойства объекта В табл. 8-4 перечислены свойства объекта DataRowView;

большинство которых доступны только для чтения.

Таблица 8-4. Свойства объекта DataRowView Свойство Тип данных Описание Возвращает объект DataView, к которому относится DataView DataView объект DataRowView. Доступно только для чтения изменяют ли запись в данный момент.

Boolean ступно только для чтения ли запись новой запи Boolean сью- Доступно только для чтения Возвращает/задает содержимое поля Object Row DataRow Возвращает для объекта DataRowView соответствующий объект DataRow. Доступно только для чтения Сообщает, какая версия соответствующего объекта DataRow доступна через объект DataRowView. Доступно только для чтения Свойство DataView Возвращает объект DataView, к которому относится объект Свойства IsEdit и IsNew Свойства IsEdit и IsNew позволяют редактируется ли в данный момент объект и если да, то как именно.

Если вы редактируете новую запись (создали новый объект DataRowView с помощью метода но еще не вызвали метод чтобы доба вить запись в базовый объект метод IsNew вернет а метод IsEdit Ч False. При редактировании уже имеющейся записи таблицы метод IsNew щает False, а метод IsEdit Ч True.

Свойство Item Функциональность свойства Item объекта DataRowView во многом аналогична функциональности одноименного свойства объекта DataRow. Свойство Item объекта DataRowView позволяет изменять и просматривать содержимое поля соответству ющей записи. Обращаться к полю посредством свойства Item можно по его име ни или порядковому номеру.

Свойство Row Функциональность объекта DataRowView немного уже объек та DataRow. Так, у DataRowView нет методов типа и Если вам необходимы возможности интерфейса DataRow, воспользуйтесь свойством Row Часть Автономная работа с данными: объект DataSet модели объекта Оно возвращает соответствующий объекту DataRowView объект DataRow.

Свойство Если вы работаете с записью данных при помощи интерфейса и вам требуется определить, какая именно версия данных доступна через Item, просмотрите значение свойства RowVersion объекта DataRowView.

Свойство RowVersion доступно только для чтения, но возвращает значение из перечисления Методы объекта DataRowView Методы объекта DataRoivView описаны в табл. 8-5.

8-5. Методы объекта DataRowView Метод Начинает процесс записи Отменяет отложенные изменения записи Создает новый объект содержащий только дочерние записи текущей записи Помечает запись как удаленную Сохраняет отложенные изменения записи Методы и Методы BeginEdit, и EndEdit объекта DataRowView работают аналогич но методам объекта DataRow. Если перед за писи вы вызовете метод сделанные изменения подтверждаются только после вызова метода EndEdit. Для их отмены воспользуйтесь методом CancelEdit.

Метод Предположим, вам нужно создать объект DataView, отображающий только дочер ние записи, связанные с конкретной записью. Для отношения клиенты Ч зака зы, о котором идет речь в этой книге, создать подобный объект DataView очень легко. свойству Table объект содержащий информацию о заказах, а свойству Ч строку типа Все выглядит весьма просто. А что, если придется проверить значение стол бца (CustomerlD) на предмет сим А если вы имеете дело с основанным на группе Объект предоставляет простое и изяшное решение этой пробле мы Ч метод CreateChildView. Вам следует лишь вызвать его и указать имя отноше объект DataRelation (так же, как и при работе с методом DataRow). Метод CreateChildView вернет новый объект DataView, исполь зующий отношение в качестве фильтра.

Pages:     | 1 |   ...   | 2 | 3 | 4 | 5 | 6 |   ...   | 8 |    Книги, научные публикации