Полное руководство. С# 4.0 - Шилдт Герберт
Шрифт:
Интервал:
Закладка:
При использовании в запросе оператора select или group иногда требуется сформировать временный результат, который будет служить продолжением запроса для получения окончательного результата. Такое продолжение осуществляется с помощьюоператора into в комбинации с оператором select или group. Ниже приведена общая форма оператора into:into имя тело_запроса
где имя обозначает конкретное имя переменной диапазона, используемой для циклического обращения к временному результату в продолжении запроса, на котороеуказывает тело_запроса. Когда оператор into используется вместе с операторомselect или group, то его называют продолжением запроса, поскольку он продолжаетзапрос. По существу, продолжение запроса воплощает в себе принцип построениянового запроса по результатам предыдущего.
ПРИМЕЧАНИЕСуществует также форма оператора into, предназначенная для использования вместе соператором join, создающим групповое объединение, о котором речь пойдет далее в этойглаве.
Ниже приведен пример программы, в которой оператор into используется вместес оператором group. Эта программа является переработанным вариантом предыдущего примера, в котором список веб-сайтов формируется по имени домена самоговерхнего уровня. А в данном примере первоначальные результаты запроса сохраняются в переменной диапазона ws и затем отбираются для исключения всех групп, состоящих менее чем из трех элементов.// Использовать оператор into вместе с оператором group.using System;using System.Linq;class IntoDemo { static void Main() { string[] websites = { "hsNameA.com", "hsNameB.net", "hsNameC.net", "hsNameD.com", "hsNameE.org", "hsNameF.org", "hsNameG.tv", "hsNameH.net", "hsNameI.tv" }; // Сформировать запрос на получение списка веб-сайтов, группируемых // по имени домена самого верхнего уровня, но выбрать только те // группы, которые состоят более чем из двух членов. // Здесь ws — это переменная диапазона для ряда групп, // возвращаемых при выполнении первой половины запроса. var webAddrs = from addr in websites where addr.LastIndexOf('.') != -1 group addr by addr.Substring(addr.LastIndexOf('.')) into ws where ws.Count() > 2 select ws; // Выполнить запрос и вывести его результаты. Console.WriteLine("Домены самого верхнего уровня " + "с более чем двумя членами.n"); foreach(var sites in webAddrs) { Console.WriteLine("Содержимое домена: " + sites.Key); foreach(var site in sites) Console.WriteLine(" " + site); Console.WriteLine(); } }}
Эта программа дает следующий результат:Домены самого верхнего уровня с более чем двумя членами.Содержимое домена: .net hsNameB.net hsNameC.net hsNameH.net
Как следует из результата выполнения приведенной выше программы, по запросувозвращается только группа .net, поскольку это единственная группа, содержащаябольше двух элементов.
Обратите особое внимание в данном примере программы на следующую последовательность операторов в формируемом запросе.group addr by addr.Substring(addr.LastIndexOf('.')) into wswhere ws.Count() >2select ws;
Сначала результаты выполнения оператора group сохраняются как временныедля последующей обработки оператором where. В качестве переменной диапазонав данный момент служит переменная ws. Она охватывает все группы, возвращаемыеоператором group. Затем результаты запроса отбираются в операторе where с такимрасчетом, чтобы в конечном итоге остались только те группы, которые содержат больше двух членов. Для этой цели вызывается метод Count(), который является методом расширения и реализуется для всех объектов типа IEnumerable. Он возвращаетколичество элементов в последовательности. (Подробнее о методах расширения речьпойдет далее в этой главе.) А получающаяся в итоге последовательность групп возвращается оператором select.Применение оператора let для создания временной переменной в запросе
Иногда возникает потребность временно сохранить некоторое значение в самомзапросе. Допустим, что требуется создать переменную перечислимого типа, которуюможно будет затем запросить, или же сохранить некоторое значение, чтобы в дальнейшем использовать его в операторе where. Независимо от преследуемой цели, этивиды функций могут быть осуществлены с помощью оператора let. Ниже приведенаобщая форма оператора let:let имя = выражение
где имя обозначает идентификатор, получающий значение, которое дает выражение.Тип имени выводится из типа выражения.
В приведенном ниже примере программы демонстрируется применение оператора let для создания еще одного перечислимого источника данных. В качестве входныхданных в запрос вводится массив символьных строк, которые затем преобразуются вмассивы типа char. Для этой цели служит еще один метод обработки строк, называемый ToCharArray() и возвращающий массив, содержащий символы в строке. Полученный результат присваивается переменной chrArray, которая затем используетсяво вложенном операторе from для извлечения отдельных символов из массива. И наконец, полученные символы сортируются в запросе, и из них формируется результирующая последовательность.// Использовать оператор let в месте с вложенным оператором from.using System;using System.Linq;class LetDemo { static void Main() { string[] strs = ( "alpha", "beta", "gamma" }; // Сформировать запрос на получение символов, возвращаемых из // строк в отсортированной последовательности. Обратите внимание // на применение вложенного оператора from. var chrs = from str in strs let chrArray = str.ToCharArray() from ch in chrArray orderby ch select ch; Console.WriteLine("Отдельные символы, отсортированные по порядку:"); // Выполнить запрос и вывести его результаты. foreach(char с in chrs) Console.Write(с + " "); Console.WriteLine(); }}
Вот к какому результату приводит выполнение этой программы.Отдельные символы, отсортированные по порядку:a a a a a b e g h l m m p t
Обратите внимание в данном примере программы на то, что в операторе let переменной chrArray присваивается ссылка на массив, возвращаемый методом str.ToCharArray().let chrArray = str.ToCharArray()
После оператора let переменная chrArray может использоваться в остальныхоператорах, составляющих запрос. А поскольку все массивы в C# преобразуются в типIEnumerable<T>, то переменную chrArray можно использовать в качестве источникаданных для запроса во втором, вложенном операторе from. Именно это и происходитв рассматриваемом здесь примере, где вложенный оператор from служит для перечисления в массиве отдельных символов, которые затем сортируются по нарастающейи возвращаются в виде конечного результата.
Оператор let может также использоваться для хранения неперечислимого значения. В качестве примера ниже приведен более эффективный вариант формированиязапроса в программе IntoDemo из предыдущего раздела.var webAddrs = from addr in websites let idx = addr.LastIndexOf('.') where idx != -1 group addr by addr.Substring(idx) into ws where ws.Count() > 2 select ws;
В этом варианте индекс последнего вхождения символа точки в строку присваивается переменной idx. Данное значение затем используется в методе Substring().Благодаря этому исключается необходимость дважды искать символ точки в строке.Объединение двух последовательностей с помощью оператора join
Когда приходится иметь дело с базами данных, то зачастую требуется формировать последовательность, увязывающую данные из разных источников. Например,в Интернет-магазине может быть организована одна база данных, связывающая наименование товара с его порядковым номером, и другая база данных, связывающая порядковый номер товара с состоянием его запасов на складе. В подобной ситуации может возникнуть потребность составить список, в котором состояние запасов товаров наскладе отображается по их наименованию, а не порядковому номеру. Для этой целипридется каким-то образом "увязать" данные из двух разных источников (баз данных).И это нетрудно сделать с помощью такого средства LINQ, как оператор join.