Слайд 1Высокоуровневые методы информатики и программирования
Лекция 16
Встроенный язык запросов
Слайд 2План работы
Введение в язык LINQ
LINQ to Object
Интерфейс IEnumerable
Примеры в Visual Studio
Отличие
от SQL
Слайд 3Постановка задачи
В программе часто требуется выполнять выборки объектов из различных источников
данных
находить элементы, которые удовлетворяют некоторым условиям,
Упорядочивать элементы,
формировать на новые объекты используя существующие.
Существует много типов источников данных, которые хранят множества объектов:
массивы;
коллекции (нетипизированные и типизированные);
XML документы;
базы данных.
Оказалось, что можно единообразно решать эти задачи для всех этих типов источников данных.
С этой целью в языке C# был разработан новый язык:
Language INtegrated Query - LINQ.
Слайд 4LINQ - Language INtegrated Query
Новая возможность языка C# 3.0;
Запросы к
источникам данных являются частью языка C#;
Стандартные операции запросов - Standard Query Operators API;
Единый язык запросов к коллекциям в памяти, XML документам и базам данных.
Слайд 5LINQ позволяет
создавать и выполнять единообразные запросы (query expressions) для работы с
любыми объектами, которые реализуют интерфейс IEnumerable (непосредственно или через расширяющие методы);
реляционными базами данных;
объектами DataSets (которые хранят данные из БД);
XML документами.
Слайд 7Архитектура LINQ
Others
C#
VB.NET
.NET Language Integrated Query (LINQ)
LINQ
to SQL
LINQ
to Objects
LINQ
to XML
LINQ
to Datasets
LINQ
to Entities
LINQ
провайдеры источников данных
ADO.NET поддержка для LINQ
Слайд 8Архитектура
Запрос LINQ
Объекты
SubmitChanges()
Запрос SQL
from c in db.Customers
where c.City == "London"
select
new {
c.Name, c.Phone }
select Name, Phone
from customers
where city = 'London'
INSERT INTO Customer …
UPDATE Customer …
DELETE FROM Customer …
db.Customers.Add(c1);
c2.City = “Seattle";
db.Customers.Remove(c3);
Слайд 9Разновидности LINQ
LINQ to Objects – для выполнения запросов к структурам данных
в оперативной памяти (System.Linq).
LINQ to SQL (DLinq) –для выполнения запросов к реляционным БД. Выполняет трансляцию LINQ запросов к объектной модели в запросы SQL и посылает их к базе данных для выполнения. После возврата результатов от БД, LINQ to SQL транслирует их назад в объекты, с которыми может работать.
LINQ to Entities – способ выполнения запросов к БД с помощью описания соответствия между классами программы и логической моделью баз данных.
LINQ to DataSet – для выполнения запросов к выборке из БД в оперативной памяти – DataSet (отсоединенной режим работы с БД).
LINQ to XML (XLinq) – для выполнения запросов к XML документам. Дает возможность искать коллекции элементов и атрибутов. Аналогичен XPath и XQuery. (System.Xml.Linq)
Слайд 10Преимущества LINQ
Единообразный способ запроса к данным.
Единый синтаксис для изучения
и запоминания.
Строго типизированные запросы - ошибки определяются уже при компиляции.
Работает подсказка IntelliSense в Visual Studio.
Слайд 11Технология LINQ to Objects
Для выполнения запросов к структурам данных в
оперативной памяти. Можно делать запросы к любому типу данных, который поддерживает интерфейс IEnumerable (C#)
Пространство имен System.Linq.
Слайд 12Интерфейс IEnumerable
Все обобщенные коллекции поддерживают этот интерфейс.
Большинство Standard Query Operators являются
расширяющими методами в статическом классе System.Linq.Enumerable и содержат первый параметр с типом IEnumerable.
Для получения доступа к Standard Query Operators необходимо добавить namespace System.Linq (содержится в DLL System.Core.dll, подключается автоматически).
Последовательность это любая коллекция, которая поддерживает данный интерфейс.
Слайд 13Общий вид LINQ запроса
var = from in
where
<условие>
orderby <ключ>
select <объект резутьтата>;
Слайд 14Операции LINQ запроса
Для записи запросов можно использовать следующие ключевые слова.
Слайд 15Грамматика выражении запросов
(Query Expressions)
При составлении выражений запросов необходимо следовать следующим
правилам:
Запрос должен начинаться с ключевого слова from.
Основная часть запроса может включать несколько ключевых слов from или where.
Слово from это генератор, который объявляет одну или более переменную перечисления, которые пробегают по элементам последовательности или объединения нескольких последовательностей.
Слово where фильтрует элементы последовательности или объединения нескольких последовательностей в результирующую последовательность.
Затем может идти слово orderby, которое содержит одно или несколько полей сортировки с возможностью указания направления сортировки (по увеличению или уменьшению значения поля).
Затем должны следовать слова select или group.
В конце запроса может быть продолжение. В продолжении м.б.
слово into (направляет результаты запроса в воображаемую последовательность вывода, которое работает как слово from для части запроса, начинающейся со слов в пункте 2),
или несколько слов join,
или другая повторяющаяся последовательность этих пронумерованных пунктов, начиная со слов в пункте № 2.
Слайд 16Методы выборки LINQ
и многие другие
Для результатов выборки можно выполнить различные методы:
Слайд 17Пример с массивом
int[] numbers = { 5, 4, 1, 3, 9,
8, 6, 7, 2, 0 };
var lowNums = from n in numbers
where n < 5 orderby n select n;
Console.WriteLine(“LINQ: Numbers < 5:");
foreach (var x in lowNums)
{ Console.WriteLine(x); }
int[] arr = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
int[] arr1 = new int[10];
int kol = 0;
for (int i = 0; i < arr.Length; i++)
{
if (arr[i] < 5) {
arr1[kol] = arr[i];
kol++;
}
}
Array.Sort(arr1,0,kol);
Console.WriteLine("Simple: Numbers < 5:");
for (int i=0;i { Console.WriteLine(arr1 [i]); }
Задача: выбрать из целочисленного массива все числа меньше 5 и упорядочить их.
Свой алгоритм
C помощью LINQ
Слайд 18Пример
Запрос к массиву
int[ ] numbers = { 10, 20,
30, 40, 1, 2, 3, 8 };
// Only print items less than 10.
IEnumerable subset = from i in numbers where i < 10 orderby i descending select i;
foreach (int i in subset)
Console.WriteLine("Item: {0}", i);
Использование var
int[ ] numbers = {10, 20, 30, 40, 1, 2, 3, 8};
// Use implicit typing here...
var subset = from i in numbers where i < 10 orderby i descending select i;
// ...and here.
foreach (var i in subset)
Console.WriteLine("Item: {0} ", i);
Слайд 19Анонимные типы
public class Customer
{
public string Name;
public Address
Address;
public string Phone;
public List
Orders;
…
}
public class Contact
{
public string Name;
public string Phone;
}
Customer c = GetCustomer(…);
Contact x = new Contact { Name = c.Name, Phone = c.Phone };
Customer c = GetCustomer(…);
var x = new { c.Name, c.Phone };
Customer c = GetCustomer(…);
var x = new { Name = c.Name, Phone = c.Phone };
class ???
{
public string Name;
public string Phone;
}
Создание анонимного
типа с инициализацией
Слайд 20LINQ стиль программирования
var contacts =
from c in customers
where c.State == "WA"
select new { c.Name, c.Phone };
class Contact { … };
List contacts = new List();
foreach(Customer c in customers)
{
if(c.State == “WA”)
{
Contact ct = new Contact();
ct.Name = c.Name;
ct.Phone = c.Phone;
contacts.Add(ct);
}
}
Слайд 21Преобразование выборки в коллекции
Результат выборки можно преобразовать в коллекции с помощью
методов
ToArray(),
ToDictionary(),
ToList().
Например:
int[] numbers = { 10, 20, 30, 40, 1, 2, 3, 8 };
// Получить результат выборки в виде массива int[].
int[] subsetAsIntArray =
(from i in numbers where i < 10 select i).ToArray();
// Получить результат выборки в виде коллекции List.
List subsetAsListOfInts =
(from i in numbers where i < 10 select i).ToList();
Слайд 22Пример преобразования
var numbers = new int[] { 1, 4, 9, 16,
25, 36 };
List numQuery2 = (from num in numbers
where (num % 2) == 0
select num).ToList();// or like this:
// numQuery3 is still an int[]
var numQuery3 = (from num in numbers
where (num % 2) == 0
select num).ToArray();
Слайд 23Пример с объектами класса
// Создаем массив объектов car.
car[
] arrayOfCars = new car[6]
{
new car("Ford",1992), new car("Fiat",1988),
new car("Buick",1932), new car("Ford",1932),
new car("Dodge",1999), new car("Honda",1977)
};
var cars = from cr in arrayOfCars
where (cr.Year<1960) select cr;
foreach (var с in cars)
{
Console.WriteLine("{0} – {1}", c.Make,c.Year);
}
public class car
{
// конструктор
public car(string make,int year)
{ Make=make; Year=year; }
// свойства
public int Year
{ get; set ;}
public string Make
{ get; set;}
}
Слайд 24LINQ и обобщенные коллекции
Пример простого класса:
class Car
{
public string Nomer =
string.Empty;
public string Color = string.Empty;
public int Speed;
public string Make = string.Empty;
}
Создание коллекции
static void Main(string[] args)
{
// Создаем обобщенную коллекцию объектов Car – List
List myCars = new List() {
new Car{Nomer = "в562ва", Color = "Silver", Speed = 160, Make = "BMW"},
new Car{Nomer = "p123то", Color = "Tan", Speed = 140, Make = "BMW"},
new Car{Nomer = "c345ке", Color = "Black", Speed = 220, Make = "VW"},
new Car{Nomer = "в654нс", Color = "Rust", Speed = 180, Make = "Yugo"},
new Car{Nomer = "с162ми", Color = "White", Speed = 250, Make = "Ford"}
};
}
Слайд 25Запрос к обобщенной коллекции
// Create a query expression.
var fastCars =
from c in myCars
where c.Speed > 200 select c;
foreach (var car in fastCars)
Console.WriteLine("{0} ездит слишком быстро!",
car.Nomer);
Слайд 26Построение запросов
Общий вид запроса
var result = from item in container
select item;
var allCars = from c in myCars select c;
var nomers = from c in myCars select c.Nomer;
var makes = (from c in myCars select c.Make).Distinct();
Запрос с условием
var result = from item in container where Boolean expression select item;
var onlyBMWs = from c in myCars where c.Make == "BMW" select c;
var onlyFastBMWs = from c in myCars
where c.Make == "BMW" && c.Speed >= 100 select c;
Создание объектов нового типа
var result = from item in container select new {…}
var makesColors = from c in myCars select new {c.Make, c.Color};
Сортировка результатов
var result = from item in container orderby value ascending/descending select item;
var subset = from c in myCars orderby c.Nomer select c;
var subset = from c in myCars where c.Speed > 55
orderby c.PetName descending select c;
Слайд 27Преобразование над IEnumerable
Преобразование в другие типы -Reverse(), ToArray(), ToList(), и др.
Извлечени
некоторых элементов - Distinct<>(), Union<>(), Intersect<>() и др.
Выполнение операций над элементами - Count<>(), Sum<>(), Min<>(), Max<>()и др.
Слайд 28Определение количества элементов
// Определяем количество элементов выборки
int numb = (from g
in currentVideoGames
where g.Length > 6 orderby g select g).Count();
Слайд 29Определение различий
static void GetDiff()
{
List myCars = new List
{ "Yugo", "Aztec",
"BMW"};
List yourCars = new List
{ "BMW", "Saab", "Aztec" };
var carDiff =(from c in myCars select c)
.Except(from c2 in yourCars select c2);
Console.WriteLine("Here is what you don't have, but I do:");
foreach (string s in carDiff)
Console.WriteLine(s); // Prints Yugo.
}
Слайд 30Классы Customer и Order
public class Customer
{
public string CustomerID
{ get; set; }
public string Name
{ get; set; }
public string City
{ get; set; }
public override string ToString()
{
return CustomerID + "\t" + City;
}
}
public class Order
{
public int OrderID
{ get ; set;}
public int ItemID
{ get; set; }
public string CustomerID
{ get; set; }
public DateTime OrderDate
{ get; set; }
public override string ToString()
{
return
string.Format("OrderID:{0} \r\nOrderName: {1} OrderDate: {2}", OrderID, OrderName, OrderDate);
}
}
Слайд 31Класс Item
public class Item
{
public int ItemID
{get;set;}
public string ItemName
{get;set;}
public string Category
{ get; set; }
public decimal UnitPrice
{get; set; }
public int UnitsInStock
{get; set; }
public override string ToString()
{
return string.Format("ItemID : {0} \r\nItemName: {1} \r\n "
+ "Category: {2} \r\nUnitPrice: {3} \r\nUnitsInStock: {4}",
ItemID, ItemName, Category, UnitPrice, UnitsInStock);
}
}
Слайд 32Коллекция заказчиков
List cust = new List
{
new Customer {
CustomerID = "ALFKI", City = "Берлин",
Name = "Франс Майер"},
new Customer { CustomerID = "BONAP", City = "Париж",
Name = "Поль Франсе" },
new Customer { CustomerID = "CONSH", City = "Лондон",
Name = "Джон Кенеди"},
new Customer { CustomerID = "EASTC", City = "Лондон",
Name = "Иван Петров" },
new Customer { CustomerID = "FRANS", City = "Торонто",
Name = "Петр Сидоров" },
new Customer { CustomerID = "LONEP", City = "Мюнхен",
Name = "Борис Байер" },
new Customer { CustomerID = "NORTS", City = "Лондон",
Name = "Елена Грин" },
new Customer { CustomerID = "THEBI", City = "Мюнхен",
Name = "Фриц Гендер" }
};
Слайд 33Коллекция товаров itemList
List itemList = new List
{
new Item
{ ItemID = 1, ItemName = "Энциклопедия", Category="Знание", UnitPrice = 55.99M,
UnitsInStock = 39 },
new Item { ItemID = 2, ItemName = "Тренажер", Category="Спорт", UnitPrice = 75.00M,
UnitsInStock = 17 },
new Item { ItemID = 3, ItemName = "Кородка для CD“, Category="Хранилище", UnitPrice = 4.99M, UnitsInStock = 13 },
new Item { ItemID = 4, ItemName = "Томатный кетчуп", Category="Продукты", UnitPrice = 0.56M, UnitsInStock = 53 },
new Item { ItemID = 5, ItemName = "Плеер IPod", Category="Развлечение", UnitPrice = 220.99M, UnitsInStock = 0 },
new Item { ItemID = 6, ItemName = "Война и мир CD", Category="Развлечение",
UnitPrice = 7.99M, UnitsInStock = 120 },
new Item { ItemID = 7, ItemName = "Война миров DVD", Category="Развлечение",
UnitPrice = 6.99M, UnitsInStock = 15 },
new Item { ItemID = 8, ItemName = "Клюквенный соус", Category=“Продукты", UnitPrice = 0.89M,
UnitsInStock = 6 },
new Item { ItemID = 9, ItemName = "Диетический рис", Category="Продукты", UnitPrice = 13.00M,
UnitsInStock = 29 },
new Item { ItemID = 10, ItemName = “Виноград", Category="Продукты", UnitPrice = 1.19M, UnitsInStock = 4 }
}
Слайд 34Коллекция заказов orderList
List orderList = new List
{
new
Order { OrderID = 1, ItemID = 2, CustomerID = "BONAP",
OrderDate = DateTime.Now },
new Order { OrderID = 2, ItemID = 5, CustomerID= "FRANS",
OrderDate = DateTime.Now },
new Order { OrderID = 3, ItemID = 7, CustomerID = "CONSH ",
OrderDate = DateTime.Now },
new Order { OrderID = 4, ItemID = 9, CustomerID = "FRANS",
OrderDate = DateTime.Now },
new Order { OrderID = 5, ItemID = 10, CustomerID = "FRANS",
OrderDate = DateTime.Now }
};
Слайд 35Простые запросы
// получение всех потребителей живущих в Лондоне
var results = from
c in cust
where c.City == "Лондон"
select c;
foreach (var c in results1) Console.WriteLine(c);
// получение всех потребителей упорядоченных по названию города и имени
var results = from с in cust
orderby c.City, c.Name
select new {c.City, c.Name}
Слайд 36
// получение всех товаров дороже 10 и упорядочение по увеличению цены
var
SelOrder = (from a in itemList where (a.UnitPrice > 10M)
orderby a.UnitPrice select a);
foreach (var obj in SelOrder)
Console.WriteLine("ItemName = {0}, UnitPrice = {1}", obj.ItemName, obj.UnitPrice);
// получение всех товаров дороже 10 и упорядочение по уменьшению цены
SelOrder = (from a in itemList where (a.UnitPrice > 10M)
orderby a.UnitPrice descending select a);
foreach (var obj in SelOrder)
Console.WriteLine("ItemName = {0}, UnitPrice = {1}", obj.ItemName, obj.UnitPrice);
// получение двух товаров дороже 10 и упорядочение по уменьшению цены,
// без самого дорогого товара
var SelOrder2 = (from a in itemList where (a.UnitPrice > 10M)
orderby a.UnitPrice descending select a).Skip(1).Take(2);
foreach (var obj in SelOrder2)
Console.WriteLine("ItemName = {0}, Price = {1}", obj.ItemName,obj.UnitPrice);
Слайд 37Связывание источников данных и создание нового класса
var itemOrders = from i
in itemList
join o in orderList on i.ItemID equals o.ItemID
select new { i.ItemName, CustomerID}
Слайд 38Отложенное выполнение
Выборка не формируется до тех пор, пока она не будет
использоваться
Пример:
int[ ] numbers = {10,20,30,40,1,2,3,8 };
// описываем выражения для получаем числа
// меньше чем 10.
var subset = from i in numbers
where i < 10 select i;
// выражение LINQ выполняется здесь!
foreach (var i in subset)
Console.WriteLine("{0} < 10", i);
Console.WriteLine();
// Меняем некоторые данные в массиве.
numbers[0] = 4;
// Опять оцениваем выражение.
foreach (var j in subset)
Console.WriteLine("{0} < 10", j);
Слайд 39Соответствие языков
LINQ и SQL
Языки LINQ и SQL имеют много общего
Язык
LINQ (интегрированный язык)
var query = from element in collection
[, from element2 in collection2]
where condition
orderby orderExpression [ascending|descending]
[, orderExpression2 ...]
select [alias = ]columnExpression[,[alias2 = ]columnExpression2]
Язык SQL (язык реляционныхбаз данных)
SELECT [Element.ColumnExpression[, Element2.ColumnExpression2]
FROM Collection AS Element[, Collection2 AS Element2]
WHERE Condition
ORDER BY OrderExpression [ASCENDING|DESCENDING][, OrderExpression2 ...]
Слайд 40Примеры запросов SQL и LINQ
SQL запрос к БД
SELECT * from Books
WHERE QuatityInStock > 50 AND Price > 50.00
LINQ запрос к коллекции объектов
var result = from b in Books where b.QuatityInStock > 50 && Price > 50.00 select b;
Слайд 41LINQ запрос к XML данным
using System;
using System.Linq;
using System.Xml.Linq;
….
// XML данные –
строка с тэгами
XElement books = XElement.Parse
(@"
Pro LINQ: Language Integrated Query in C# 2008
Joe Rattz
Pro WF: Windows Workflow in .NET 3.0
Bruce Bukovics
Pro C# 2005 and the .NET 2.0 Platform, Third Edition
Andrew Troelsen
");
// LINQ запрос к XML документу
var titles =
from book in books.Elements("book")
where (string) book.Element("author") == "Joe Rattz"
select book.Element("title");
// выводим результаты
foreach(var title in titles)
Console.WriteLine(title.Value);
Слайд 42Простой LINQ запрос к базе данных SQL Server
using System;
using System.Linq;
using System.Data.Linq;
using
nwind; //
// создаем объект для доступа к БД Northwind
Northwind db = new Northwind(@"Data Source=.\SQLEXPRESS;Initial Catalog=Northwind");
// LINQ запрос к таблице Customer в объекте db
var custs =
from c in db.Customers
where c.City == "Rio de Janeiro"
select c;
// вывод полученных результатов
foreach (var cust in custs)
Console.WriteLine("{0}", cust.CompanyName);