Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Разработка приложений баз данных (Visual Studio 2008).docx
Скачиваний:
143
Добавлен:
26.03.2016
Размер:
1.01 Mб
Скачать

Универсальные методы Field и SetField (linq to DataSet)

LINQ to DataSet реализует методы расширений класса DataRowдля доступа к значениям столбцов:FieldиSetField. Эти методы предоставляют разработчикам более простой доступ к значениям столбцов, особенно в отношении значений NULL. ОбъектDataSetиспользует для представления значений NULL классValue, тогда как LINQ использует поддержку платформой .NET Framework 2.0 типов, допускающих значения NULL. Использование существующего метода доступа столбцов в объектеDataRowтребует приведения возвращаемого объекта к нужному типу. Если определенное поле в объектеDataRowможет иметь значение NULL, необходимо явно проверить наличие значения NULL, поскольку при возвращении объектаValueи неявном приведении его к другому типу возникает исключениеInvalidCastException. В следующем примере, если методIsNullне использовался для проверки на значение NULL, возникнет исключение, если индексатор возвращает объектValueи пытается привести его к типуString.

C#

// Fill the DataSet.

DataSet ds = new DataSet();

ds.Locale = CultureInfo.InvariantCulture;

FillDataSet(ds);

DataTable products = ds.Tables["Product"];

var query =

from product in products.AsEnumerable()

where !product.IsNull("Color") &&

(string)product["Color"] == "Red"

select new

{

Name = product["Name"],

ProductNumber = product["ProductNumber"],

ListPrice = product["ListPrice"]

};

foreach (var product in query)

{

Console.WriteLine("Name: {0}", product.Name);

Console.WriteLine("Product number: {0}", product.ProductNumber);

Console.WriteLine("List price: ${0}", product.ListPrice);

Console.WriteLine("");

}

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

В следующем примере используется метод Field.

C#

// Fill the DataSet.

DataSet ds = new DataSet();

ds.Locale = CultureInfo.InvariantCulture;

FillDataSet(ds);

DataTable products = ds.Tables["Product"];

var query =

from product in products.AsEnumerable()

where product.Field<string>("Color") == "Red"

select new

{

Name = product.Field<string>("Name"),

ProductNumber = product.Field<string>("ProductNumber"),

ListPrice = product.Field<Decimal>("ListPrice")

};

foreach (var product in query)

{

Console.WriteLine("Name: {0}", product.Name);

Console.WriteLine("Product number: {0}", product.ProductNumber);

Console.WriteLine("List price: ${0}", product.ListPrice);

Console.WriteLine("");

}

Обратите внимание, что тип данных, определяемый в универсальном параметре T метода Fieldи методаSetField, должен совпадать с типом базового значения. В противном случае возникнет исключениеInvalidCastException.Указанное имя столбца также должно совпадать с именем столбца вDataSet, в противном случае возникнет исключениеArgumentException. В обоих случаях исключения возникают во время выполнения при перечислении данных в ходе выполнения запроса.

Метод SetFieldсам по себе не выполняет преобразования типов. Однако это не означает, что преобразование типов не происходит. МетодSetFieldреализует поведение ADO.NET 2.0 классаDataRow. Преобразование типов может быть выполнено объектомDataRow, а преобразованное значение затем будет сохранено в объектеDataRow.

Перекрестные запросы между таблицами (LINQ to DataSet)

Кроме запросов к отдельной таблице, LINQ to DataSetпозволяет выполнять межтабличные запросы, которые выполняются с помощью соединений. Соединение представляет собой взаимосвязь объектов одного источника данных с объектами, использующими общий атрибут, например идентификатор продукта или контактного лица, в другом источнике данных. В объектно-ориентированном программировании связи между объектами относительно просты для перемещения, так как каждый объект содержит элементы, ссылающиеся на другой объект. Однако в таблицах внешних баз данных перемещение по связям выполняется не столь просто. Таблицы баз данных не содержат встроенных связей. В таких случаях для соединения элементов из разных источников может потребоваться операция объединения. Например, если две таблицы содержат данные о продуктах и о продажах, нужно использовать операцию соединения для сопоставления данных о продажах и о продуктах, относящихся к одному и тому же заказу на продажу.

LINQ (Language-Integrated Query) реализует два оператора соединения: JoinиGroupJoin. Эти операторы выполняют эквивалентные соединения, то есть соединения, связывающие два источника данных по равенству ключей. (В отличие от этого, Transact-SQL поддерживает операторы соединения, отличные от equals, например оператор less than.)

В терминах реляционной базы данных оператор Joinвыполняет внутреннее соединение. Внутреннее соединение представляет собой соединение, при котором возвращаются только объекты, имеющие соответствия в другом наборе данных.

Операторы GroupJoinне имеют прямых аналогов в реляционных базах данных, используют надмножества внутренних соединений и левых внешних соединений. Левое внешнее соединение представляет собой соединение, возвращающее каждый элемент первой (левой) коллекции, даже если он не имеет соответствующих элементов во второй коллекции.

Дополнительные сведения о соединениях см. в разделе Операции соединения.

Пример

C#

// Fill the DataSet.

DataSet ds = new DataSet();

ds.Locale = CultureInfo.InvariantCulture;

FillDataSet(ds);

DataTable orders = ds.Tables["SalesOrderHeader"];

DataTable details = ds.Tables["SalesOrderDetail"];

var query =

from order in orders.AsEnumerable()

join detail in details.AsEnumerable()

on order.Field<int>("SalesOrderID") equals

detail.Field<int>("SalesOrderID")

where order.Field<bool>("OnlineOrderFlag") == true

&& order.Field<DateTime>("OrderDate").Month == 8

select new

{

SalesOrderID =

order.Field<int>("SalesOrderID"),

SalesOrderDetailID =

detail.Field<int>("SalesOrderDetailID"),

OrderDate =

order.Field<DateTime>("OrderDate"),

ProductID =

detail.Field<int>("ProductID")

};

foreach (var order in query)

{

Console.WriteLine("{0}\t{1}\t{2:d}\t{3}",

order.SalesOrderID,

order.SalesOrderDetailID,

order.OrderDate,

order.ProductID);

}