Опубликован: 04.05.2010 | Уровень: для всех | Доступ: платный
Лекция 8:

Проектирование баз данных и работа с ними Веб-приложений. LINQ, ADO.NET Entities, DDD

10.1.1.5.2. Выбор подмножества каждого исходного элемента

Существует два основных способа выбора подмножества каждого элемента в исходной последовательности.

  1. Чтобы выбрать только один член исходного элемента, используйте обращение к свойствам. В следующем примере предполагается, что объект Customer содержит несколько открытых свойств, включая строку с именем City. При выполнении этот запрос создаст выходную последовательность строк:
    var query = from cust in Customers
                select cust.City;
  2. Для создания элементов, содержащих более одного свойства исходного элемента, можно использовать инициализатор объектов либо с именованным объектом, либо с анонимным типом. В следующем примере показано использование анонимного типа для инкапсуляции двух свойств из каждого элемента Customer:
    var query = from cust in Customer
                select new {Name = cust.Name, City = cust.City};
10.1.1.5.3. Преобразование находящихся в памяти объектов в XML

Запросы LINQ упрощают преобразования данных между структурами данных в памяти, базами данных SQL, наборами данных ADO.NET и потоками или документами XML. В следующем примере объекты в находящейся в памяти структуре данных преобразуются в XML-элементы:

class XMLTransform
{
    static void Main()
    {            
        // Создание источника данных, используя инициализацию коллекции
        List<Student> students = new List<Student>()
        {
            new Student {First="Светлана", Last="Омельченко", ID=111, City="Москва", Scores= new List<int> {5, 4, 5, 3}},
            new Student {First="Кристина", Last="Лаврова", ID=112, City="Тюмень", Scores= new List<int> {5, 3, 3, 4}},
            new Student {First="Иван", Last="Моргунов", ID=113, City="Новосибирск", Scores= new List<int> {5, 5, 5, 4}},
        };
        // Создание запроса
        var studentsToXML = new XElement("Root",
            from student in students
            let x = String.Format("{0},{1},{2},{3}", student.Scores[0],
                    student.Scores[1], student.Scores[2], student.Scores[3])
            select new XElement("student",
                       new XElement("First", student.First),
                       new XElement("Last", student.Last),
                       new XElement("Scores", x)
                    ) 
                ); 
        // Выполнение запроса
        Console.WriteLine(studentsToXML);
        Console.WriteLine("Нажмите любую кнопку для выхода!");
        Console.ReadKey();
    }
}

Код формирует следующие выходные XML-данные:

<Root>
  <student>
    <First>Светлана</First>
    <Last>Омельченко</Last>
    <Scores>5,4,5,3</Scores>
  </student>
  <student>
    <First>Кристина</First>
    <Last>Лаврова</Last>
    <Scores>5,3,3,4</Scores>
  </student>
  <student>
    <First>Иван</First>
    <Last>Моргунов</Last>
    <Scores>5,5,5,4</Scores>
  </student>
</Root>
10.1.1.5.4. Выполнение операций над исходными элементами

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

Примечание.Вызов методов в выражениях запроса не поддерживается, если запрос будет перенесен в какой-либо другой домен. Например, невозможно вызвать обычный C# метод в LINQ to SQL, так как в SQL Server для него отсутствует контекст. Тем не менее, хранимые процедуры можно сопоставить методам и вызывать последние:
class FormatQuery
{
    static void Main()
    {            
        // Источник данных
        double[] radii = { 1, 2, 3 };
        // Запрос
        IEnumerable<string> query =
            from rad in radii
            select String.Format("Area = {0}", (rad * rad) * 3.14);
        // Выполнение запроса 
        foreach (string s in query)
            Console.WriteLine(s);
        Console.WriteLine("Нажмите любую кнопку для выхода!");
        Console.ReadKey();
    }
}
/* На выходе будет получено:
    Area = 3.14
    Area = 12.56
    Area = 28.26
*/
10.1.1.6. Связи типов в операциях запроса

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

Операции запросов LINQ строго типизированы в источнике данных, в самом запросе и при выполнении запроса. Тип переменных в запросе должен быть совместим с типом элементов в источнике данных и с типом переменной итерации в операторе foreach. Строгая типизация гарантирует перехват ошибок во время компиляции, когда их можно будет исправить прежде, чем с ними столкнутся пользователи.

10.1.1.6.1. Запросы, не выполняющие преобразование исходных данных

На рис. 10.4 показана операция запроса LINQ to Objects, не выполняющая преобразование данных. Источник содержит последовательность строк, результат запроса также является последовательностью строк.

Операция запроса LINQ to Objects, не выполняющая преобразование данных

Рис. 10.4. Операция запроса LINQ to Objects, не выполняющая преобразование данных

Источник:Связи типов в операциях запроса ( LINQ ) [2]

  1. Аргумент типа источника данных определяет тип переменной диапазона.
  2. Тип выбранного объекта определяет тип переменной запроса. Здесь name является строкой. Следовательно, переменная запроса является IEnumerable <string>.
  3. Итерация переменной запроса выполняется в операторе foreach. Поскольку переменная запроса является последовательностью строк, переменная итерации также является строкой.
10.1.1.6.3. Запросы, выполняющие преобразование исходных данных

На рис. 10.5 показана операция запроса LINQ to SQL, выполняющая простое преобразование данных. В качестве входных данных запрос получает последовательность объектов Customer и выбирает в результате только свойство Name. Поскольку Name является строкой, запрос создает последовательность строк в качестве выходных данных.

Операция запроса LINQ to Objects, выполняющая простое преобразование данных

Рис. 10.5. Операция запроса LINQ to Objects, выполняющая простое преобразование данных

Источник:Связи типов в операциях запроса ( LINQ ) [2]

  1. Аргумент типа источника данных определяет тип переменной диапазона.
  2. Оператор select возвращает свойство Name вместо целого объекта Customer. Поскольку Name является строкой, аргумент типа custNameQuery является string, а не Customer.
  3. Поскольку custNameQuery является последовательностью строк, переменная итерации цикла foreach также должна быть string.

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

Операция запроса LINQ to Objects, выполняющая сложное преобразование данных

Рис. 10.6. Операция запроса LINQ to Objects, выполняющая сложное преобразование данных

Источник:Связи типов в операциях запроса ( LINQ ) [2]

  1. Аргумент типа источника данных всегда является типом переменной диапазона в запросе.
  2. Так как оператор select создает анонимный тип, переменная запроса должна быть неявно типизирована с помощью var.
  3. Поскольку тип переменной запроса неявный, переменная итерации в цикле foreach также должна быть неявной.
10.1.1.6.5. Разрешение компилятору определять сведения о типе

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

Определение компилятором сведений о типе

Рис. 10.7. Определение компилятором сведений о типе

Источник:Связи типов в операциях запроса ( LINQ ) [2]

Зарина Каримова
Зарина Каримова
Казахстан, Алматы, Гимназия им. Ахмета Байтурсынова №139, 2008
Akiyev Begench
Akiyev Begench
Беларусь, Полоцк, полоцкий государственный университет