c# desktop. Занятие 13

29
Темы лекции: LINQ. Практическое задание: LINQ. Тренер: Игорь Шкулипа, к.т.н. Платформа .Net и язык программирования C#. Занятие 13

Upload: igor-shkulipa

Post on 12-Apr-2017

64 views

Category:

Education


1 download

TRANSCRIPT

Page 1: C# Desktop. Занятие 13

Темы лекции: LINQ.

Практическое задание: LINQ.

Тренер: Игорь Шкулипа, к.т.н.

Платформа .Net и язык программирования C#.

Занятие 13

Page 2: C# Desktop. Занятие 13

http://www.slideshare.net/IgorShkulipa 2

LINQ

Традиционно запросы к данным выражаются в виде простых строк безпроверки типов при компиляции или поддержки IntelliSense. Крометого, разработчику приходится изучать различные языки запросов длякаждого из типов источников данных: баз данных SQL, XML-документов, различных веб-служб и т. д. LINQ делает запросы оченьудобной конструкцией языков C# и Visual Basic. Разработчики создаютзапросы к строго типизированным коллекциям объектов с помощьюзарезервированных слов языка и знакомых операторов.

Language-Integrated Query (LINQ) - язык интегрированных запросов.

LINQ позволяет извлекать информацию из различных источников данных.В основу LINQ положено понятие запроса, в котором определяетсяинформация получаемая из источника данных. После формированиязапроса происходит его выполнение.

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

Доступно несколько реализаций LINQ: LINQ to Objects, LINQ to SQL, LINQto DataSet, LINQ to Entities и LINQ to XML.

Page 3: C# Desktop. Занятие 13

http://www.slideshare.net/IgorShkulipa 3

Пример

class PersoneInfo

{

public string Name { get; set; }

public string Surname { get; set; }

public string Middle { get; set; }

public DateTime BirthDate { get; set; }

public override string ToString()

{

return

String.Format

("{0} {1} {2} : {3}", Surname, Name, Middle, BirthDate);

}

}

Page 4: C# Desktop. Занятие 13

http://www.slideshare.net/IgorShkulipa 4

Пример

static void Main(string[] args)

{

List<PersoneInfo> people = new List<PersoneInfo> {

new PersoneInfo{

Name="Ivan",

Surname="Ivanov",

Middle="Ivanovich",

BirthDate=DateTime.Parse("1/1/1980")},

new PersoneInfo{

Name="Petr",

Surname="Petrov",

Middle="Petrovich",

BirthDate=DateTime.Parse("2/2/1990")},

new PersoneInfo{

Name="Sidor",

Surname="Sidorov",

Middle="Sidorovich",

BirthDate=DateTime.Parse("3/3/1985")}

};

Page 5: C# Desktop. Занятие 13

http://www.slideshare.net/IgorShkulipa 5

Пример

var resultQuery1 = from persone in people

where persone.BirthDate > DateTime.Parse("1/1/1985")

orderby persone.Surname, persone.Name

select new { Name = persone.Name, Surname = persone.Surname };

var resultQuery2 = from persone in people

where persone.BirthDate > DateTime.Parse("1/1/1985")

orderby persone.Surname, persone.Name

select persone;

foreach (var per in resultQuery1)

{

Console.WriteLine(per.ToString());

}

foreach (var per in resultQuery2)

{

Console.WriteLine(per.ToString());

}

Console.ReadKey();

}

{ Name = Petr, Surname = Petrov }

{ Name = Sidor, Surname = Sidorov }

Petrov Petr Petrovich : 02.02.1990 0:00:00

Sidorov Sidor Sidorovich : 03.03.1985 0:00:00

Page 6: C# Desktop. Занятие 13

http://www.slideshare.net/IgorShkulipa 6

Расширяющие методы и лямбда-выражения

В пространстве имен System.Linq есть два статический класса, которыесодержат множество расширяющих методов – Enumerable и Queryable.

Классы Enumerable и Queryable предоставляют набор расширяющихметодов для интерфейсов IEnumerable и IQueryable соответственно.

Имена этих расширяющих методов совпадают с именами конструкцийзапросов. Это не случайно, так как, в действительности, эти методыреализуют операции запросов LINQ.

Интерфейс IQueryable предназначен для реализации поставщикамизапросов. Он реализуется только поставщиками, которые такжереализуют интерфейс IQueryable<T>. Если поставщик не реализуетIQueryable<T>, для его источника данных не могут использоватьсястандартные операторы запросов.

Интерфейс IQueryable наследует интерфейс IEnumerable, поэтому если онпредставляет запрос, результаты этого запроса будут допускатьперечисление.

Page 7: C# Desktop. Занятие 13

http://www.slideshare.net/IgorShkulipa 7

Тот же пример с расширяющими методами

var resultQuery3 = people

.Where(persone => persone.BirthDate > DateTime.Parse("1/1/1985"))

.OrderBy(persone => persone.Surname)

.OrderBy(persone => persone.Name)

.Select(persone => new { Name = persone.Name, Surname = persone.Surname });

var resultQuery4 = people

.Where(persone => persone.BirthDate > DateTime.Parse("1/1/1985"))

.OrderBy(persone => persone.Surname)

.OrderBy(persone => persone.Name)

.Select(persone => persone);

foreach (var per in resultQuery3)

{

Console.WriteLine(per.ToString());

}

foreach (var per in resultQuery4)

{

Console.WriteLine(per.ToString());

}{ Name = Petr, Surname = Petrov }

{ Name = Sidor, Surname = Sidorov }

Petrov Petr Petrovich : 02.02.1990 0:00:00

Sidorov Sidor Sidorovich : 03.03.1985 0:00:00

Page 8: C# Desktop. Занятие 13

http://www.slideshare.net/IgorShkulipa 8

Синтаксис LINQ

Каждое выражение запроса начинается с конструкции from, котораяобъявляет переменную диапазона.

Конструкция from, похожа на оператор foreach в том, что онаосуществляет итерацию по элементам коллекции people, сохраняя накаждом шаге очередной элемент коллекции в переменной persone.

После конструкции from следуют различные операции запроса дляфильтрации данных переменной диапазона.

В примере применяются операции where и orderby.

Выражение закрывается операцией проекции (select). Применениеоперации проекции обычно приводит к созданию новой коллекции –результата выполнения запроса.

101 LINQ Samples

Основные конструкции LINQ

Page 9: C# Desktop. Занятие 13

http://www.slideshare.net/IgorShkulipa 9

Ключевые слова запросов LINQ

from, join, where, group, into, let, ascending,

descending, on, equals, in, orderby, select

Page 10: C# Desktop. Занятие 13

http://www.slideshare.net/IgorShkulipa 10

Конструкция from

Каждый запрос начинается с конструкции from. Конструкция from – этогенератор, который определяет переменную диапазона - локальнуюпеременную, используемую для представления каждого элементавходной коллекции, по мере применения к ней выражения запроса.

Выражения запроса может содержать более одной конструкции from.

Пример – генерация таблицы умножения.

var multTable = from a in Enumerable.Range(1, 10)

from b in Enumerable.Range(1, 10)

select new { A = a, B = b, AB = a * b };

foreach (var item in multTable)

{

Console.WriteLine("{0}*{1}={2}", item.A, item.B, item.AB);

}

1*1=1

1*2=2

1*3=3

1*4=4

1*5=5

1*6=6

...

10*6=60

10*7=70

10*8=80

10*9=90

10*10=100

Page 11: C# Desktop. Занятие 13

http://www.slideshare.net/IgorShkulipa 11

Конструкция join

Конструкция join может использоваться для сопоставления данных издвух различных источников.

class PersoneInfo

{

public string Name { get; set; }

public string Surname { get; set; }

public string Middle { get; set; }

public DateTime BirthDate { get; set; }

public string NationalityID { get; set; }

public override string ToString()

{

return String

.Format("{0} {1} {2} : {3}", Surname, Name, Middle, BirthDate);

}

}

class PersoneNationality

{

public string ID { get; set; }

public string Name { get; set; }

}

Page 12: C# Desktop. Занятие 13

http://www.slideshare.net/IgorShkulipa 12

Пример join

List<PersoneInfo> people = new List<PersoneInfo> {

new PersoneInfo{

Name="Ivan",

Surname="Ivanov",

Middle="Ivanovich",

NationalityID="222",

BirthDate=DateTime.Parse("1/1/1980")},

new PersoneInfo{

Name="Petr",

Surname="Petrov",

Middle="Petrovich",

NationalityID="111",

BirthDate=DateTime.Parse("2/2/1990")},

new PersoneInfo{

Name="Sidor",

Surname="Sidorov",

Middle="Sidorovich",

NationalityID="111",

BirthDate=DateTime.Parse("3/3/1985")}

};

List<PersoneNationality> nationalities =

new List<PersoneNationality> {

new PersoneNationality{

ID= "111",

Name="Ukraine"},

new PersoneNationality{

ID="222",

Name="Russian"}

};

Page 13: C# Desktop. Занятие 13

http://www.slideshare.net/IgorShkulipa 13

Пример join

var resultQuery = from persone in people

join nation in nationalities

on persone.NationalityID equals nation.ID

orderby nation.Name descending

select new

{

Name = persone.Name,

Surname = persone.Surname,

Middle = persone.Middle,

Nationality = nation.Name

};

foreach (var per in resultQuery)

{

Console.WriteLine("{0} {1} {2} - {3}",

per.Surname, per.Name, per.Middle, per.Nationality);

}

Petrov Petr Petrovich - Ukraine

Sidorov Sidor Sidorovich - Ukraine

Ivanov Ivan Ivanovich - Russian

Page 14: C# Desktop. Занятие 13

http://www.slideshare.net/IgorShkulipa 14

Конструкция where

Конструкция where – это конструкция фильтров. Она следует законструкциями from и join.

Фильтры состоят из ключевого слова where, за которым следуетвыражение условия.

var resultQuery1 =

from persone in people

where persone.BirthDate > DateTime.Parse("1/1/1985")

orderby persone.Surname, persone.Name

select new { Name = persone.Name, Surname = persone.Surname };

var resultQuery2 =

from persone in people

where persone.BirthDate > DateTime.Parse("1/1/1985")

orderby persone.Surname, persone.Name

select persone;

Page 15: C# Desktop. Занятие 13

http://www.slideshare.net/IgorShkulipa 15

Конструкция orderby

Конструкция orderby используется для сортировки результатов запроса.За ключевым словом orderby следует элемент, по значению которогодолжна проводиться сортировка, обычно это какое-то свойствопеременной диапазона.

Сортировку можно выполнять как в порядке возрастания (ascending) таки в порядке убывания (descending). Если ключевое слово явно неуказано, то принимается сортировка по возрастанию (ascending).

var resultQuery = from persone in people

join nation in nationalities

on persone.NationalityID equals nation.ID

orderby nation.Name descending,

persone.Name ascending,

persone.Surname

select new

{

Name = persone.Name,

Surname = persone.Surname,

Middle = persone.Middle,

Nationality = nation.Name

};

Page 16: C# Desktop. Занятие 13

http://www.slideshare.net/IgorShkulipa 16

Конструкция select

Конструкция select служит для производства конечного результатазапроса. Она называется проектором, по этому проектирует(транслирует) данные внутри запроса в форму, удобную дляприменения.

Компилятор преобразует конструкцию select в вызов расширяющегометода Select. Тело конструкции select преобразуется в лямбда-выражение, передаваемое методу Select, который использует его дляпроизводства каждого элемента результирующего набора.

var multTable = from a in Enumerable.Range(1, 10)

from b in Enumerable.Range(1, 10)

select new { A = a, B = b, AB = a * b };

Page 17: C# Desktop. Занятие 13

http://www.slideshare.net/IgorShkulipa 17

Конструкция let

Конструкция let предоставляет новый локальный идентификатор, накоторый можно ссылаться в следующей части запроса.

var letQuery = from persone in people

let fullName = persone.Name + " " +

persone.Middle + " " +

persone.Surname

orderby fullName descending

select fullName;

foreach (var fname in letQuery)

{

Console.WriteLine(fname);

}

Sidor Sidorovich Sidorov

Petr Petrovich Petrov

Ivan Ivanovich Ivanov

Page 18: C# Desktop. Занятие 13

http://www.slideshare.net/IgorShkulipa 18

Конструкция group

Конструкция gourp является средством для разбиения входных данныхзапроса на части.

Конструкция gourp - это проектор, который проектирует данные вколлекцию интерфейсов IGrouping.

Интерфейс IGrouping определен в пространстве имен System.Linq иунаследован от IEnumerable. По этому IGrouping можно применятьвезде, где можно применять IEnumerable.

Интерфейс IGrouping включает свойство по имени Key, которое являетсяобъектом, описывающим подмножество.

Каждый результирующий набор формируется применением операцииэквивалентности к входным данными Key.

Page 19: C# Desktop. Занятие 13

http://www.slideshare.net/IgorShkulipa 19

Пример group

var groupQuery = from number in Enumerable.Range(0, 50)

group number by number % 2;

foreach (var group in groupQuery)

{

Console.WriteLine("\nmod2={0}", group.Key);

foreach (var number in group)

{

Console.Write("{0}, ", number);

}

}

mod2=0

0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30,

32, 34, 36, 38, 40, 42, 44, 46, 48,

mod2=1

1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31,

33, 35, 37, 39, 41, 43, 45, 47, 49,

Page 20: C# Desktop. Занятие 13

http://www.slideshare.net/IgorShkulipa 20

Конструкция into

Конструкция into подобна использованию конструкции let в том, что онаопределяет локальную переменную внутри запроса.

Использование конструкции into сообщает компилятору о присвоениирезультата конструкций group или join в локальную переменную,которая будет использоваться позднее в следующей части запроса.

Конструкцию into еще называют конструкцией продолжения,поскольку конструкции group и into не являются окончанием запроса.

Конструкцию into так же работает как генератор, подобно конструкцииfrom и идентификатор, предоставленный into во многом подобенпеременной диапазона from.

Page 21: C# Desktop. Занятие 13

http://www.slideshare.net/IgorShkulipa 21

Пример into

var intoQuery = from number in Enumerable.Range(0, 50)

group number by number % 2 into groups

select new

{

Key = groups.Key,

Count = groups.Count(),

Numbers = groups

};

foreach (var item in intoQuery)

{

Console.WriteLine("\nmod2={0}", item.Key);

Console.WriteLine("Count={0}", item.Count);

foreach (var number in item.Numbers)

{

Console.Write("{0}, ", number);

}

}

var intoQuery = from number in Enumerable.Range(0, 50)

group number by number % 2 into groups

where groups.Key == 0

select new

{

Key = groups.Key,

Count = groups.Count(),

Numbers = groups

};

mod2=0

Count=25

0, 2, 4, 6, 8, 10, 12,

14, 16, 18, 20, 22, 24,

26, 28, 30, 32, 34, 36,

38, 40, 42, 44, 46, 48,

mod2=0

Count=25

0, 2, 4, 6, 8, 10, 12,

14, 16, 18, 20, 22, 24,

26, 28, 30, 32, 34, 36,

38, 40, 42, 44, 46, 48,

mod2=1

Count=25

1, 3, 5, 7, 9, 11, 13,

15, 17, 19, 21, 23, 25,

27, 29, 31, 33, 35, 37,

39, 41, 43, 45, 47, 49,

Page 22: C# Desktop. Занятие 13

http://www.slideshare.net/IgorShkulipa 22

Пример LINQ запроса

Dictionary<string, List<string>> dictionary =

new Dictionary<string, List<string>>

{

{"привет",

new List<string>{"пирвет", "првиет", "првет"}},

{"пока",

new List<string>{"поак", "пка"}},

{"дела",

new List<string>{"деал", "дила", "дла", "дкла"}},

{"хорошо",

new List<string>{"хрошо", "хоршо", "хроошо"}},

{"удачи",

new List<string>{"удкчи", "уадчи", "удачм"}}

};

string wrongText =

"\n- пирвет! как деал?\n" +

"- првиет! дила хоршо.\n" +

"- хрошо, удачм.\n" +

"- поак.\n";

Page 23: C# Desktop. Занятие 13

http://www.slideshare.net/IgorShkulipa 23

Пример LINQ запроса

string[] words =

wrongText.Split(new char[] { ' ', '!', '.', ',', '?', '-' });

var correctDict = from dict in dictionary

let wrongWords = dict.Value

from val in wrongWords

join word in words on val equals word

select new

{

WrongWord = word,

CorrectWord = dict.Key

};

string correctText = wrongText;

foreach (var item in correctDict)

{

correctText =

correctText.Replace(item.WrongWord, item.CorrectWord);

}

Console.WriteLine("Wrong Text: {0}", wrongText);

Console.WriteLine("Correct Text: {0}", correctText);

Wrong Text:

- пирвет! как деал?

- првиет! дила хоршо.

- хрошо, удачм.

- поак.

Correct Text:

- привет! как дела?

- привет! дела хорошо.

- хорошо, удачи.

- пока.

Page 24: C# Desktop. Занятие 13

http://www.slideshare.net/IgorShkulipa 24

LINQ to Objects

Термином "LINQ to Objects" называют использование запросов LINQнепосредственно с коллекциями IEnumerable или IEnumerable<T> безпромежуточных поставщиков LINQ или API-интерфейсов, таких как LINQ to SQLили LINQ to XML. LINQ можно использовать для запроса любых перечислимыхколлекций, таких как List<T>, Array или Dictionary<TKey, TValue>.

По сути, LINQ to Objects представляет новый подход к коллекциям. Раньше нужнобыло писать сложные циклы foreach, которые определяли способ извлеченияданных из коллекции. При применении подхода LINQ создается декларативныйкод с описанием необходимых извлекаемых данных.

Кроме того, запросы LINQ имеют три основных преимущества перед традиционнымициклами foreach.

• Они более компактные и удобочитаемые, особенно при фильтрации понескольким условиям.

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

• Они могут быть перенесены на другие источники данных с минимальнымиизменениями или без изменений.

В общем случае, чем более сложные операции следует выполнить над данными, тембольше преимуществ от применения LINQ вместо использования традиционныхметодов итераций.

Ссылка на раздел MSDN

Page 25: C# Desktop. Занятие 13

http://www.slideshare.net/IgorShkulipa 25

LINQ to Entities

LINQ to Entities обеспечивает поддержку LINQ при запросах ксущностям.

Компонент позволяет разработчикам писать запросы к концептуальноймодели Entity Framework на языке Visual Basic или Visual C#.

Запросы к платформе Entity Framework представляются в виде деревакоманд запроса, выполняемого на контексте объектов.

Технология LINQ to Entities преобразует запросы LINQ в запросы в видедерева команд, выполняет эти запросы на платформе Entity Frameworkи возвращает объекты, которые могут использоваться как платформойEntity Framework, так и технологией LINQ.

Ссылка на раздел MSDN

Page 26: C# Desktop. Занятие 13

http://www.slideshare.net/IgorShkulipa 26

LINQ to DataSet

LINQ to DataSet упрощает и ускоряет выполнение запросов к данным,кэшированным в объекте DataSet. В особенности LINQ to DataSetупрощает создание запросов, позволяя писать их непосредственно наязыке программирования, а не применять отдельный язык запросов.

Использование метода Select для выборки всех строк из таблицы Productи отображения названий продуктов.

// Fill the DataSet.

DataSet ds = new DataSet();

ds.Locale = CultureInfo.InvariantCulture;

FillDataSet(ds);

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

IEnumerable<DataRow> query =

from product in products.AsEnumerable()

select product;

Console.WriteLine("Product Names:");

foreach (DataRow p in query)

{

Console.WriteLine(p.Field<string>("Name"));

}

Ссылка на раздел MSDN

Page 27: C# Desktop. Занятие 13

http://www.slideshare.net/IgorShkulipa 27

LINQ to XML

LINQ to XML обеспечивает интерфейс программирования для работы сXML в памяти на основе платформы .NET LINQ Framework. LINQ to XMLиспользует новейшие возможности языка платформы .NET Frameworkи может быть сравним с обновленным, переработанным программныминтерфейсом XML модели DOM.

Пример: как найти элемент с определенным атрибутом.

XElement root = XElement.Load("PurchaseOrder.xml");

IEnumerable<XElement> address =

from el in root.Elements("Address")

where (string)el.Attribute("Type") == "Billing"

select el;

foreach (XElement el in address)

Console.WriteLine(el);

Ссылка на раздел MSDN

Page 28: C# Desktop. Занятие 13

http://www.slideshare.net/IgorShkulipa 28

LINQ to SQL

LINQ to SQL является компонентом .NET Framework, предоставляющиминфраструктуру времени выполнения для управления реляционнымиданными как объектами.

В LINQ to SQL модель данных реляционной базы данных сопоставляетсяобъектной модели, выраженной в языке программированияразработчика. При запуске приложения LINQ to SQL преобразуетзапросы LINQ из объектной модели в SQL и отправляет их в базуданных для выполнения. Когда база данных возвращает результаты,LINQ to SQL преобразует их обратно в объекты, с которыми можноработать на собственном языке программирования.

Ссылка на раздел MSDN

Page 29: C# Desktop. Занятие 13

http://www.slideshare.net/IgorShkulipa 29

Лабораторная работа №13. LINQ

В индивидуальном курсовом проекте, реализовать доступ к данным спомощью LINQ:

• если используется база данных – LINQ to SQL

• если используется XML – LINQ to XML

• для итерации по коллекциям, по возможности использовать LINQto Objects