Upload
igor-shkulipa
View
59
Download
1
Embed Size (px)
Citation preview
Темы лекции: LINQ.
Практическое задание: LINQ.
Тренер: Игорь Шкулипа, к.т.н.
Платформа .Net и язык программирования C#.
Занятие 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.
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);
}
}
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")}
};
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
http://www.slideshare.net/IgorShkulipa 6
Расширяющие методы и лямбда-выражения
В пространстве имен System.Linq есть два статический класса, которыесодержат множество расширяющих методов – Enumerable и Queryable.
Классы Enumerable и Queryable предоставляют набор расширяющихметодов для интерфейсов IEnumerable и IQueryable соответственно.
Имена этих расширяющих методов совпадают с именами конструкцийзапросов. Это не случайно, так как, в действительности, эти методыреализуют операции запросов LINQ.
Интерфейс IQueryable предназначен для реализации поставщикамизапросов. Он реализуется только поставщиками, которые такжереализуют интерфейс IQueryable<T>. Если поставщик не реализуетIQueryable<T>, для его источника данных не могут использоватьсястандартные операторы запросов.
Интерфейс IQueryable наследует интерфейс IEnumerable, поэтому если онпредставляет запрос, результаты этого запроса будут допускатьперечисление.
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
http://www.slideshare.net/IgorShkulipa 8
Синтаксис LINQ
Каждое выражение запроса начинается с конструкции from, котораяобъявляет переменную диапазона.
Конструкция from, похожа на оператор foreach в том, что онаосуществляет итерацию по элементам коллекции people, сохраняя накаждом шаге очередной элемент коллекции в переменной persone.
После конструкции from следуют различные операции запроса дляфильтрации данных переменной диапазона.
В примере применяются операции where и orderby.
Выражение закрывается операцией проекции (select). Применениеоперации проекции обычно приводит к созданию новой коллекции –результата выполнения запроса.
101 LINQ Samples
Основные конструкции LINQ
http://www.slideshare.net/IgorShkulipa 9
Ключевые слова запросов LINQ
from, join, where, group, into, let, ascending,
descending, on, equals, in, orderby, select
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
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; }
}
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"}
};
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
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;
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
};
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 };
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
http://www.slideshare.net/IgorShkulipa 18
Конструкция group
Конструкция gourp является средством для разбиения входных данныхзапроса на части.
Конструкция gourp - это проектор, который проектирует данные вколлекцию интерфейсов IGrouping.
Интерфейс IGrouping определен в пространстве имен System.Linq иунаследован от IEnumerable. По этому IGrouping можно применятьвезде, где можно применять IEnumerable.
Интерфейс IGrouping включает свойство по имени Key, которое являетсяобъектом, описывающим подмножество.
Каждый результирующий набор формируется применением операцииэквивалентности к входным данными Key.
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,
http://www.slideshare.net/IgorShkulipa 20
Конструкция into
Конструкция into подобна использованию конструкции let в том, что онаопределяет локальную переменную внутри запроса.
Использование конструкции into сообщает компилятору о присвоениирезультата конструкций group или join в локальную переменную,которая будет использоваться позднее в следующей части запроса.
Конструкцию into еще называют конструкцией продолжения,поскольку конструкции group и into не являются окончанием запроса.
Конструкцию into так же работает как генератор, подобно конструкцииfrom и идентификатор, предоставленный into во многом подобенпеременной диапазона from.
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,
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";
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:
- привет! как дела?
- привет! дела хорошо.
- хорошо, удачи.
- пока.
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
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
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
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
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
http://www.slideshare.net/IgorShkulipa 29
Лабораторная работа №13. LINQ
В индивидуальном курсовом проекте, реализовать доступ к данным спомощью LINQ:
• если используется база данных – LINQ to SQL
• если используется XML – LINQ to XML
• для итерации по коллекциям, по возможности использовать LINQto Objects