Lab06

advertisement
Министерство образования Республики Беларусь
Министерство образования и науки Российской Федерации
ГУВПО “Белорусско-Российский университет”
Кафедра “Программное обеспечение информационных технологий”
Дисциплина “Объектно-ориентированное программирование
и проектирование ”
Лабораторная работа № 06
Использование средства LINQ
для работы с данными
Время выполнения работы – 4 часа
2014
2
1 Цель работы
Ознакомление с технологией LINO и ее использованием для работы с данными.
2 Техническое обеспечение
2.1 Персональная ЭВМ IBM Pentium III и более поздних моделей c оперативной
памятью не менее 512 Мбайт.
2.2 Клавиатура.
2.3 Дисплей.
2.4 Манипулятор типа “мышь”.
3 Программное обеспечение
3.1 Операционная система Windows XP SP 3 более поздние версии Windows.
3.2 Система программирования Microsoft Visual Studio 2008 и более поздние версии.
4 Постановка задачи
Разработать Windows-приложения согласно варианта задания, которые приведены в
разделе 6, используя табличный ввод и вывод данных.
5 Использование технологии LINQ
Технология LINQ (Language Integrated Query) предназначена для обработки (запросов
и преобразований) практически любого типа источника данных, начиная от массивов, файлов, строк, коллекций объектов .NET Framework, баз данных SQL Server, наборов данных
ADO.NET (DataSet) и XML-документов. LINQ упрощает ситуацию, предлагая единообразные стандартные шаблоны для работы с данными в различных видах источников и форматов данных. Стандартные шаблоны включают в себя основные операции запросов LINQ:
фильтрация, упорядочение, группировка, соединение, выбор (проецирование), статистическая обработка. По форме синтаксис языка LINQ очень похож на язык запросов SQL. В данной главе рассмотрим типичные LINQ-запросы и преобразования к некоторым источникам
данных.
5.1 LINQ-запрос к массиву данных
LINQ-запрос представляет собой выражение, извлекающее данные из источника данных. Все операции запроса LINQ состоят из трех различных действий: получение источника
(в нашем случае — это присвоение Начальных значений исходному массиву) данных, создание запроса (начинается с предложения from) и непосредственное выполнение запроса
(обычно это цикл foreach). В данном разделе рассмотрим две задачи, первая — из массива
имен извлекаем имена длиной шесть символов, записывая их или в список (коллекцию), или
в новый массив. Другая -задача— из массива целых чисел выбираем только те, значения которых больше четырех, также записывая результат запроса в список или массив.
Итак, запустим Visual Studio 2010, закажем новый проект шаблона Windows Forms
Application С#. Затем из панели элементов перенесем в форму текстовое поле. Далее через
щелчок правой кнопкой мыши перейдем к вкладке программного кода (листинг 19.1).
Л ис ти н г 1 9 .1. Из в л еч е ни е да нн ы х из масс и в о в
// Реш а ем дв е за да чи по в ы б о р у эл еме нтов из ма с сив а с п ом ощ ь ю ста нда ртны х
// за пр ос ов те х но ло г ии LI NQ
us i ng S ys te m ;
us i ng S ys te m . Li nq ;
us i ng S ys te m .W in do w s .F or ms ;
3
// Др у г ие ди ре ктив ы us i ng у да ле ны , п о с ко ль к у о ни н е и сп о ль з у ют ся в да нн ой пр о гра мме
na me spa ce Li nq 1
{
p ubl i c p a rti a l cl a s s Fo rm 1 : F or m
{
p u bli c F or m1 ()
{
I nit ia l ize Com po ne nt() ;
t his . Te xt = " Те хн ол о гия LI NQ " ; t e xtB ox 1 .M u lti li ne = tr u e;
// ЗА ДАЧ А 1 :
// И з ма с си в а им е н в ы б ра ть им ен а с к о ли че ств о м б у кв ра в ны м ш е ст и,
// в ы в е с ти э ти и ме на в т ек ст ов ое пол е Te xt Bo x в а л фа в итно м по ря д ке, пр и
// эт ом в с е б у кв ы п е ре в ес ти в в ер хний ре г ис тр .
// Ре ш е н ие :
st ri ng Ст ро ка И ме н = "В и тя Ла ри са Ла р иса Лена Ан др ей Жен я " +
"А ле к са н др Л а ри са Ви кто р Св ета О кс а на На т а ш а " ;
// И з ст ро ки име н п ол у ча ем ма с си в име н, за да в а я в ка ч еств е сепа ра т ора
// де ле н ия п од ст ро к с имв о л п роб е ла :
st ri ng[ ] И ме н а = Ст ро ка И ме н. Sp lit( ' ' );
// или п рощ е : str in g[] И м ена =
//
{ "В итя " , " Ла ри са " , " Ла ри са ", " Лена ", "Ан др ей ", " Ж е ня ",
//
"А ле к с а нд р" , " Ла р ис а " , " Ви к тор " , "Св е та " , "О к са н а ", "На та ш а " } ;
te xtB ox 1 . Te x t = "З АДА ЧА 1 . В спи с ке име н : \r\ n\ r\ n" ;
f or e a c h (s tri n g x i n И ме н а )
te xt Bo x 1. Te xt = te xtB o x1 . Te xt + x + " ";
// В ре з у ль т а те LI NQ -з а пр о са п о л уч а ем с пи со к им ен с ко ли ч е ств ом б у кв
// ра в ны м ш е ст и:
va r За п ро с = f ro m s i n И ме на
w h e re s. Le ng th = = 6 // - у с лов ие в ы б ора
or d e rb y s // - со рти ров а т ь в а лфа в итн ом по ря д ке
se l e ct s . To U ppe r() ; / / - п ерев о д в в е рх ний ре г и ст р
// s - эт о пе ре ме нна я д иа па зо на сх ожа с пе рем енн ой итера ци и в f or ea c h
// Уда ля е м э ле м е нты - ду бли ка ты и з спи с ка име н:
За пр ос = За про с .D is ti n ct() ;
// И ли та ки м об ра з ом :
// За п ро с = За п ро с. U n io n( З а п ро с) ;
te xtB ox 1 . Te x t = te xt Bo x 1. Te xt + " \ r\n \r\ n " +
"в ы б ира е м и мен а с к ол иче ств ом б у кв ра в ны м ш е ст и, пр и " +
"э том и зб а в л яем с я от д уб лир ов а н ия име н: \r\ n\ r \n " ;
f or e a c h (s tri n g x i n За п ро с) // x - п ерем енна я ит ера ци и в ц и кле fo rea ch
te xt Bo x 1. Te xt = te xtB o x1 . Te xt + x + " ";
te xtB ox 1 . Te x t = te xt Bo x 1. Te xt + " \ r\n \r\ n " ;
//~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
// ЗА ДА Ч А 2 : И з ма с сив а ц елы х чи се л X[] тре бу ет ся в ы б ра ть чи сла ,
//
зн а че ни я к ото ры х > = 4 , и за п и са ть эти ч ис л а в спи с ок Y ,
//
от с орт иро в а в в ы б ра нны е чи с ла п о в оз ра ста н и ю.
// Ре ш е н ие :
// И ни циа ли з а ци я ма с с ив а це лы х ч исе л :
i nt[] X = { -2 , 5, - 2 3 , 0, 7, - 1 0, 11 , 1 1 , 1 4, 3 , 8 , 5 , - 5 , 2 7 , 8 };
te xtB ox 1 . Te x t + = " З АДА ЧА 2 . И з з а да н но г о ма с си в а X : \ r\n \r\ n " ;
f or e a c h (i nt x i n X)
te xt Bo x 1. Te xt = te xtB o x1 . Te xt + x + " " ;
te xtB ox 1 . Te x t = te xt Bo x 1. Te xt + " \ r\n \r\ nв ы би ра е м чи сл а , з на ч ения " +
" кот ор ы х > = 4 и за пи сы в а е м и х в с пи со к ( ко лл е к ци ю) Y , " +
"и с кл юча я эл е ме нты -д уб ли ка ты : \ r\ n\r\ n " ;
// Y - это сп ис о к, к у да по мещ а ет с я в ы бра нны е э ле мент ы :
va r Y = f rom x i n X
w he re x > = 4 // - у сл ов и е в ы бора
4
o rde r b y x / / - со рти ру ем п о в озр а с та ни ю
se le ct x;
// Та к им об р а зо м мо ж но п ол у чить рез у ль та т за пр ос а в ма с с ив :
// in t[] Y = ( fr om x i n X / / З дес ь Y - эт о уже ма с сив ;
//
w h e re x > = 4 // - у с лов и е в ы бо ра ;
//
ord e rb y x / / - со рти ру ем по в оз ра ста ни ю ;
//
se l e ct x) . T oAr ra y() ; / / - прео бра зов а ние сп и с ка в ма с сив
// Уда ля е м э ле м е нты - ду бли ка ты и з спи с ка це лы х чи се л :
va r Z = Y . Di s tin ct () ;
// И ли та ки м об ра з ом :
// va r Z = Y . U ni o n(Y) ;
// Вы в о д э ле ме нт о в сп ис ка Y в м е тк у tex tB ox 1 :
f or e a c h ( va r z i n Z)
te xt Bo x 1. Te xt = te xtB o x1 . Te xt + z. T o Str in g() + " " ;
}
}
}
Как видно из программного кода, после присвоения массиву Имена начальных значений создаем запрос, который предусматривает выбор (sele ct ) из (fr om ) массива Имена
строк длиной (Le n gt h ) ровно шесть символов (условие w here ). Запись выбранных имен выполняется в список З а про с с сортировкой списка в алфавитном порядке имен. Далее для
удаления повторяющихся имен в списке используем функцию D is t in ct . В комментарии показано, как можно для этой же цели использовать функцию u ni on , которая, вообще говоря,
находит объединение двух множеств, т. е. выбирает в двух списках одинаковые элементы с
удалением повторяющихся элементов. Поскольку мы объединяем два одинаковых списка,
то получаем просто удаление повторяющихся элементов. Цикл f orea c h выводит список
За п ро с в текстовое поле te xt Bo x 1 .
Следующая задача, решенная в данном программном коде, аналогична. Задан массив
целых чисел X . Из этого массива выбираем в список Y элементы массива, значения которых
больше или равны четырем. В комментарии показано, как можно записать результаты
LINQ-запроса в массив. Удаление повторяющихся элементов в списке выполнено также с
использованием функции Di sti n ct .
На рис. 19.1 приведен фрагмент работы программы.
Рис ун о к 1 9. 1  LI N Q - з а про сы к ма с сив а м да нны х
5
Убедиться в работоспособности программы можно, открыв решение Li n q1 .s l n папки
Li nq 1 .
5.2 LINQ-запрос к коллекции (списку) данных
В некоторых случаях хранение данных в коллекции (скажем, в списке типа List) может оказаться более эффективным, чем в массиве. Например, если число элементов в массиве при работе изменяется часто или нельзя предсказать максимальное количество необходимых элементов, то можно получить большую производительность при использовании
коллекции. Но если размер не изменяется или изменяется довольно редко, то массив, пожалуй, более эффективен. Как всегда, производительность в большей степени зависит от конкретного приложения. Как советуют в документации MSDN, часто стоит потратить время на
испытание и массива, и коллекции, чтобы выбрать наиболее практичный и эффективный
вариант.
Решим три типичных задачи, их условия сформулируем при объяснении работы программы. Запустим Visual Studio 2010, закажем новый проект шаблона Windows Forms Application С#. Затем из панели элементов перенесем в форму текстовое поле. Далее через щелчок правой кнопкой мыши перейдем к вкладке
программного кода (листинг 19.2).
Л ис ти н г 1 9 .2. Из в л еч е ни е да нн ы х из с пис к о в
// Реш а ем тр и ра з лич ны х за да ч и п о в ы бо р у эл еме нто в ( об ъе кто в ) из спи с ка с по м о щ ь ю
// ста н да р тны х з а пр о сов те хн ол о гии LI NQ
us i ng S ys te m ;
us i ng S ys te m .C oll e c ti o ns . Ge ne r i c;
us i ng S ys te m . Li nq ;
us i ng S ys te m .W in do w s .F or ms ;
// Др у г ие ди ре ктив ы us i ng у да ле ны , п о с ко ль к у о ни н е и сп о ль з у ют ся в да нн ой пр о гра мме
na me spa ce Li nq 2
{
p ubl i c p a rti a l cl a s s Fo rm 1 : F or m
{
p u bli c F or m1 ()
{
I nit ia l ize Com po ne nt() ;
t his . Te xt = " Те хн ол о гия LI NQ " ; t e xtB ox 1 .M u lti li ne = tr u e;
// ЗА ДАЧ А 1. И з сп и ска стр о к в ы б ра ть н уж ны е за пи с и з а да в у с лов ие в ы б ора
te xtB ox 1 . Te x t = "З АДА ЧА 1 : Из сп ис ка име н: \r\ n " ;
// Об ъ яв л е н ие спи с ка ст ро к и е г о за п ол нени е:
va r Спи с ок = ne w Li st <s tri n g> { " В итя ", " Св ета " , "Ан д ре й" ,
" Ла р иса " , "Ма ш а " , " На та ш а " };
// или va r Сп ис о к = ne w Li st <st ri n g> () ; // - спи с ок стр о к
// Спи с ок .A d d(" Вит я ") ; С пи со к .Ad d ("Св ета ") ; Спи с ок .A dd ("А нд рей ") ;
// Спи с ок .A d d(" Ла ри са ") ; С пи со к . Add( " Ма ш а ") ; Спи с ок . Add( " На та ш а ") ;
// Не к ото ры е ма н ип ул я ции с о сп ис ко м :
i nt n = С пи с ок .C o u nt ; // К ол -в о э лем ент ов в с пи ск е:
// П ол у че ние из с пи с ка е г о эле мен та с ин де с ом 3 ( ка к в ма с сив е) :
st ri ng A = Сп ис о к.E le me nt At <s tri ng >( 4) ;
B oo le a n О тв е т = С пи со к .R em o ve( " Ла р иса ") ; // - у да лен ие и з спи с ка
// Пр е об ра з о в а ть спи с ок в ст ро к ов ы й ма с сив :
st ri ng[ ] Ма с с ив Стр о к = Спи с о к. T o Arra y() ;
f or e a c h ( va r x i n Сп ис о к)
te xt Bo x 1. Te xt = te xtB o x1 . Te xt + x . To Str i ng() + " " ;
te xtB ox 1 . Te x t + = " \r\ nв ы бира е м и мена д лин ой ч еты ре си мв о ла : \r \n " ;
// Спи с ок Вы б ра нны хИ ме н - эт о н о в ы й спи с ок , к у да поп а да ют в ы бра н ны е
// ст ро ки в р е з уль та те L IN Q - за п ро са :
va r Спи с ок В ы б ра нны хИ мен = fr o m Им я in Сп ис о к
6
w h e re Им я. Le n gth = = 4 // - у сл ов ие в ы бо ра
or de r b y И мя // - со рти ров а ть сп и с о к Z
se le c t И мя ;
// Вы в о д с пи с ка в ы б ра нны х име н в те кс тов ое по ле te xt Bo x1 :
f or e a c h ( va r x i n Сп ис о кВы б ра нны хИм ен )
te xt Bo x 1. Te xt = te xtB o x1 . Te xt + x . To Str i ng() + " " ;
//~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
// ЗА ДАЧ А 2.
te xtB ox 1 . Te x t + =
"\r \n \r\ n З АДАЧ А 2 : И з спи с ка с отр у дни к ов пре дп рия тия " +
"в ы б и ра е м не ку рящ и х дл я п ов ы ш ения з а р пла ты : \ r\ n\r\ n " ;
// За п о лняе м сп и со к с отр у дн ик ов :
L ist < Со тр у дн ик > Со тр у дни ки = ne w L ist < Со тр у дни к >{
ne w С отр у д ник {И мя = "К а ра п у зов а Ири на " , Во зра ст = 2 7 , К у рит Ли = tr ue },
ne w С отр у д ник {И мя = " Зиб ор ов В икт ор " , Во зра ст = 4 7, Ку рит Ли = fa lse } ,
ne w С отр у д ник {И мя = " Ло ма чин с ка я Св ет ла на " , Во зра ст = 3 4,
К ури т Ли = fa l se },
ne w С отр у д ник {И мя = "С то рож ен ко Св е тла на " , Во зра с т= 3 4, К у р ит Ли = fa lse },
ne w С отр у д ник {И мя = "Е р еме нк о Та ть яна ", В оз ра ст = 34 , К у рит Ли = tr ue },
ne w С отр у д ник {И мя = " По гр еби ц к ий О ле г ", В оз ра с т = 42 , К у рит Ли = tr ue },
};
va r Спи с ок Не к уря щ их Со тр у дни к ов = f rom С отр у дн и к i n Сот ру д ни ки
w he re Сот ру дн ик . Ку рит Ли = = f a lse
ord erb y С отр у дни к .И мя
sele ct С от ру дн ик ;
// Вы в о д с пи с ка н е к у рящ и х с отр у д ник ов в те к ст ов о е п о ле t ext Bo x 1 :
f or e a c h ( va r x i n Сп ис о кН ек у рящ и х Сот ру д ни ков )
te xt Bo x 1. Te xt = te xtB o x1 . Te xt + str i ng .F or ma t( "{ 0 } - в оз ра ст " +
" - { 1 } \r\ n ", x .И мя , x .В оз ра ст ) ;
//~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
// ЗА ДАЧ А 3.
te xtB ox 1 . Te x t + = " \r\ n ЗА ДАЧ А 3 : И з спи с ка ст у де нтов фа ку ль те та " +
" в ы б ира е м дв о ечн и ков : \ r\ n\ r \n " ;
// Ка ж ды й э л е ме нт в сп ис ке со де р жит фа м ил ию ст у дент а и п о лу чен ны е
// им те к ущ и е о це нк и :
L ist < Ст у де нт > Ст у де нты = new Lis t< Ст уд ент >
{
ne w Ст у де н т {Фа ми лия = " Зиб ор ов ", О цен ки = n ew Li st <i n t> { 5, 4, 4 , 5} },
ne w Ст у де н т {Фа ми лия = "С то рож ен ко " , О ц ен ки = ne w Li st <i nt > { 3, 3, 2 , 3 }} ,
ne w Ст у де н т {Фа ми лия = " Ло ма чин с ка я " , О це н ки = new Li st <i nt > { 3, 4 , 4 , 5} },
ne w Ст у де н т {Фа ми лия = " По г реби ц кий " , О ц ен ки = ne w Li st <i nt > { 2, 4 , 3 , 2} },
ne w Ст у де н т {Фа ми лия = " Лев оч ки н ", О цен к и = new L ist < i nt > { 3, 3 , 4 , 3} }
};
// Дл я до ст у па к в н ут ре нн ем у с пи с ку о ц ено к пр ед л оже ние Fr om
// ис по ль з уе м дв а ра за :
va r Спи с ок Д в ое ч ни ков = fr om Ст у ден т i n Ст у дент ы
fr om О це нка i n С ту ден т.О ц ен ки
w he re О цен ка < = 2
or de r by Ст у де нт. Фа м ил ия
se l e c t new { Ст у д ент. Фа ми лия , О ц ен ка } ;
f or e a c h ( va r Сту д ик i n Спи с о кДв ое чни к ов )
te xt Bo x 1. Te xt + = st ri ng . Fo rma t (" С ту д ент { 0} " +
" им е е т о це н к у : { 1} \r\ n ", Сту д ик . Фа м ил ия, Ст у ди к .О цен ка ) ;
// Стр о ка с о ст у де нт о м По гр еби ц к им в ы в о дит ся дв а ра з а , п о с ко ль ку о н
// име е т дв е дв ой ки
}
}
// Объ яв л яе м кла с с, со де рж а щ и й и мя с о тру д ни ка , е го в о зра ст , а та кже
7
}
// инф ор ма ци ю , к у рит ли он :
p ubl i c cla ss С отр у д ни к
{
p u bli c st ri ng И м я { ge t ; se t ; }
p u bli c i nt Во зра ст { ge t ; se t ; }
p u bli c b ool К у ри тЛи { ge t ; set ; }
}
// Объ яв л яе м кла с с, со де рж а щ и й фа м ил ию с ту де нта и спи с о к по л уче нны х и м о ц е н ок :
p ubl i c cla ss Ст у де н т
{
p u bli c st ri ng Фа мил ия { ge t ; set ; }
p u bli c L ist < i nt > О це н ки { get ; set ; }
}
Первая задача довольно простая и очень похожа на задачи, которые мы решали с помощью технологии LINQ в предыдущем примере. Здесь, в этой новой задаче вместо массива имен требуется создать список имен, а далее из этого списка выбрать имена длиной четыре символа. Решение этой задачи, построение LINQ- запроса аналогично решению задачи
из предыдущего примера, отличие состоит лишь в применении синтаксиса манипуляций со
списком типа Li st , а не с массивом. Здесь также приведены некоторые важные техники для
манипуляции списком, в частности получение элемента списка по указанному индексу
(аналогия с массивом), удаление элемента, преобразование списка в строковый массив.
Вторая задача заключается в том, чтобы создать список сотрудников предприятия и
из этого списка выбрать некоторых сотрудников по какому-либо признаку, например тех,
кто не курит. При создании списка объявлен класс Сот р у дни к , который содержит три свойства: Имя , Во зра ст и булеву переменную К у рит Ли . В начале решения заполняем список сотрудников, а затем строим LINQ-запрос для заполнения списка некурящих сотрудников.
Этот список выводим в текстовое поле t ext B ox 1, используя цикл fo rea c h .
Третья задача немного сложнее. Требуется создать список студентов факультета, содержащий фамилию студента и список полученных им текущих оценок, т. е. список оценок
должен быть "вложен" в список студентов. Из списка студентов необходимо выбрать тех,
кто имеет в списке своих оценок хотя бы одну двойку. Для решения этой задачи вначале
объявляем новый класс Ст у де н т , который имеет в качестве свойств класса фамилию студента и список (типа Li st ) оценок. Далее в начале решения третьей задачи мы привели синтаксис заполнения списка студентов. Затем строим LINQ-запрос, где, поскольку нам необходимо искать элемент списка внутри "вложенного" списка, мы используем предложение
From два раза. Поскольку студент Погребицкий имеет две двойки в списке своих текущих
оценок, он в списке двоечников фигурирует дважды (рис. 19.2).
8
Рис ун о к 1 9. 2  Т ри LI NQ -за пр ос а к сп ис ка м да нны х
Убедиться в работоспособности программы можно, открыв решение Li n q2 .s l n папки
Li nq 2 .
5.3 Группировка элементов списка с помощью LINQ-запроса
В данном примере используем стандартный шаблон LINQ-запроса для группировки
элементов списка. Программа формирует список продуктов питания. Следует организовать
такие LINQ-запросы, которые разделят искомый список на две группы по критерию цены
(больше или меньше 90 руб. за единицу) и вычислят среднюю цену по каждой группе продуктов.
Для решения этой задачи запустим Visual Studio 2010 и выберем проект шаблона
Windows Forms Application, укажем имя Name — LinqЦеныНаПродукты. Далее, попав в
конструктор формы, из панели элементов Toolbox (Панель элементов) перетащим текстовое
поле TextBox для вывода в него групп списка. В свойствах текстового поля разрешим ввод
множества строк, для этого свойство M ul til in e переведем в состояние t ru e . Затем на вкладке
программного кода введем текст, представленный в листинге 19.3.
Л ис ти н г 1 9 .3. Гр уп п и ро в ка эл е ме н то в спис ка с п ом о щ ью L IN Q -з ап р ос о в
// П ро г ра м ма ф ор мир уе т с пи со к не к ото ры х пр о ду кт ов пита ния . Перв ы й LI NQ - за пр о с
// гр уп пир уе т э ле ме н ты с пи с ка п о к рите ри ю це ны : в перв ом спи с ке о ка зы в а ют с я
// п р о д у кты , це на за е ди ни ц у к ото ры х м ен ь ш е и ли ра в на 9 0 р уб ., а в о в т ор ом ,
// со отв ет ст в е нн о, б о ль ш е 9 0 р уб. Вт ор ой LI NQ - за пр о с в ы чи сл я ет сре дн ю ю ц ен у
// пр о д у кта по ка ж до й гр упп е . Ре зу ль та ты за пр о сов в ы в о д ят ся в те кс тов ое по ле .
us i ng S ys te m ;
us i ng S ys te m .C o ll e c ti o ns . Ge ne r i c;
us i ng S ys te m . Li nq ;
us i ng S ys te m .W in do w s .F or ms ;
// Др у г ие ди ре ктив ы us i ng у да ле ны , п о с ко ль к у о ни н е и сп о ль з у ют ся в да нн ой пр о гра мме
na me spa ce Li nq Це ны Н а Пр о ду кт ы
{
p ubl i c p a rti a l cl a s s Fo rm 1 : F or m
{
p u bli c F or m1 ()
{
I nit ia l ize Com po ne nt() ;
te xtB ox 1 .M u l tili ne = t ru e ;
ba se . T e xt = "Г р упп ир ов ка э ле мен тов сп ис ка с п ом ощ ь ю LI N Q - за п ро са " ;
9
// За п о лняе м сп и со к пр од у кт ов :
L ist < Пр о д у кт > Пр о д ук ты = n ew Li s t< Пр о ду к т >{
ne w Пр о д у кт { На и мен ов а ние =" Т в о ро г ", Цена = 1 12 . 5 0F } ,
ne w Пр о д у кт { На и мен ов а ние =" Х леб " ,
Ц ена = 1 8. 7 5 F } ,
ne w Пр о д у кт { На и мен ов а ние =" Пе чень е" , Цена = 9 3. 7 5 F } ,
ne w П р о д у кт { На и мен ов а ние =" Ча й " ,
Цена = 7 6. 2 5 F } ,
ne w Пр о д у кт { На и мен ов а ние =" Мя с о ",
Цен а = 1 50 . 0 0 F } ,
ne w Пр о д у кт { На и мен ов а ние =" Г реч ка " , Цена = 6 2. 5 0 F } ,
};
va r За п ро с 1 =
f ro m П i n Пр о д ук ты
gr o up П b y ne w
{
Крит е ри й = П .Цен а > 9 0 ,
}
int o g
se le ct g ;
va r За п ро с 2 =
fr o m p i n Пр од у кты
g r ou p p b y p . Цена > 9 0 int o g
s e l e ct n e w
{
g. Ke y,
Сре д Це на По Гр у ппе = g. Av era ge(p = > p . Ц е на )
};
S in gle С ре дЦ е на П оГ р уппе 1 = З а пр ос 2 .E le me ntAt ( 0). Сре дЦе на П о Гр упп е;
S in gle С ре дЦ е на П оГ р уппе 2 = З а пр ос 2 .E le me ntAt ( 1). Сре дЦе н а П о Гр упп е;
// Вы в о д ре з уль та т ов обо их за п ро сов в т ек с тов ое по ле :
f or e a c h ( va r Гр упп а i n За пр ос 1)
{
i f ( Гр уппа .Ke y. Кр ите рий == fa l se)
te xtB ox 1. T e xt + = " \r \n Цены 9 0 р уб и ли мень ш е :" ;
e lse
te xt Bo x 1. Te xt + = " \r\ nЦ ены бо ль ш е 9 0 р уб :" ;
fo re a c h ( v a r П ро д i n Гр уп па )
{
te xtB ox 1. T e xt + = Str i ng .F or m a t(" \r\ n{ 0} - { 1} " ,
П ро д .На имен ов а н ие, П ро д .Це на );
}
i f ( Гр уппа .Ke y. Кр ите рий == fa l se)
te xtB ox 1. T e xt + = Str i ng .F or m a t(
"\r \ nС ре дня я цена п о да нной гр уп пе = { 0} р у б. \r \ n " ,
Сре д Цена По Гр уп пе 2 );
e lse
te xtB ox 1. T e xt + = Str i ng .F or m a t(
"\r \ nС ре дня я цена п о да нной гр уп пе = { 0} р у б. \r \ n " ,
Сре д Цена По Гр уп пе1 );
}
}
}
p ubl i c cla ss П ро д у к т
{
p u bli c S tri ng Н а име н ов а н ие { ge t; s et ; }
p u bli c S in gle Це на { ge t ; se t ; }
}
}
В начале программы формируем список продуктов питания. Для этого объявляем новый класс продукт, в котором для каждого продукта задаем два поля: наименование продукта и его цену. После заполнения списка продуктов (для упрощения в этом списке всего
10
шесть продуктов) задаем первый LINQ-запрос, обеспечивающий деление списка на две
группы. Второй LINQ-запрос вычисляет среднюю цену продукта по каждой группе. Вывод
результатов обоих запросов организуем с помощью двух вложенных циклов f orea c h .
Фрагмент работы программы показан на рис. 19.3.
Рис ун о к 1 9. 3  Гр уп п иров ка с пи с к а с по мо щ ь ю L I NQ -за п ро с ов
Убедиться в работоспособности программы можно, открыв решение L in qЦе н ы На П ро д у кты .s ln папки Li nq Це ны На Пр од у кты .
5.4 LINQ-запрос к словарю данных Dictionary
Замечательной структурой данных является словарь Di cti o na r y . Он представляет собой совокупность (коллекцию) ключей и значений. То есть каждый элемент (запись), добавляемый в словарь, состоит из значения V a l ue и связанного с ним ключа Ke y . Извлечение
значения по его ключу происходит очень быстро, поскольку класс Di ct io na ry < Ke y,V a l ue >
реализован как хэш-таблица. Каждый ключ в словаре D ic ti on a r y < Key ,V a l ue > должен быть
уникальным, т. е. единственным в своем роде, эксклюзивным. При добавлении в коллекцию
Dictionary очередного элемента так называемый компаратор проверяет на равенство уникальность нового ключа. Ключ не может быть пустым (n ull ), а значение может, если тип
значения value является ссылочным типом. Возможно создание словаря, в котором не различается регистр символов. Использование словаря Di ct io na r y может существенно повлиять
на эффективность алгоритма, на простоту его понимания и легкость программной реализации.
Задача, решаемая в данном примере, состоит в том, чтобы продемонстрировать возможность выбора элементов из словаря данных Di ct io na ry с помощью LINQ-запроса. В
начале программы зададим массив сотрудников некого учреждения, а затем массив сотрудников преобразуем в словарь D ic ti on a r y . Причем в качестве ключа к каждому элементу словаря зададим имя сотрудника, которое является уникальным. По ключу можно получить все
остальные сведения о сотруднике, записанные в словарь. Кроме того, с помощью LINQзапроса к словарю можно получать новую коллекцию сотрудников по какому-либо условию
(предложение w he re ). Здесь мы зададим выбор сотрудников, чей возраст превышает 33 года
(возраст Иисуса Христа). ’
Для решения этой задачи запустим Visual Studio 2010 и выберем проект шаблона
Console Application, укажем имя Name — Li nq D ic ti ona r y . Затем на вкладке программного
кода введем текст, представленный в листинге 19.4.
Л ис ти н г 1 9 .4. Ор г а низ а ц ия L IN Q-з ап р оса к сл о ва рю Dic t i on ary
//
//
//
//
За д а ем ма с сив с от ру дн ик ов у чр еж дени я . И з это г о ма сс ив а с о зда ем с л ов а рь
сот р уд ни ков , а в к а че ств е к л юча к это м у с лов а р ю в ы би ра е м имя с от ру д ни ка .
С по м ощ ь ю LI NQ - за про са из ма с сив а с от ру дн ик ов в ы бир а ем т ех, ч ей в оз ра ст
пр ев ы ш а е т 3 5 ле т . При в ы в о де ре з уль та та за пр оса на пе ча ть уч иты в а е м, ч то
11
// гов ор я п ро в о зра ст , мы го в ор им "4 7 ле т" , н о " 3 4 го да " . Т о е ст ь ес ли из в о зра ста
// в ы ч ес ть чи сл о к ра т ное 1 0 , т о при о ста тк е ме нь ш е 5 , г ов о рят , на при мер , " 3 4 г о да " ,
// а при о ста тк е б оль ш е и ли ра в н о 5, гов о рят " 4 7 лет " .
us i ng S ys te m ;
us i ng S ys te m . Li nq ;
// Др у г ие ди ре ктив ы us i ng у да ле ны , п о с ко ль к у о ни н е и сп о ль з у ют ся в да нн ой пр о гра мме
na me spa ce Li nq Di ct io n a ry
{
c la s s P ro gra m
{
sta ti c v oi d Ma i n( stri n g[] a rg s)
{
C on so le . Tit le = "L I NQ -за п ро с к сл о в а рю Di cti o na r y " ;
// Со з да е м м а с сив с отр у дн ик ов у ч реж дени я :
va r Сот р уд ни ки = ne w [ ] {
ne w {И мя = " Ка ра пу зов а И рина ", Во зра ст = 2 7, К ур ит Ли = tr ue } ,
ne w {И мя = " Зиб ор ов Ви кт ор ", В озр а с т = 4 7, К у рит Ли = fa l se },
ne w {И мя = " Л ома чин с ка я Св е тл а на " , Во зра ст = 3 1, К ур ит Ли = f a ls e } ,
ne w {И мя = " Сто ро ж е н ко Св е тла на " , Во зра ст = 34 , К у рит Ли = fa l se },
ne w {И мя = "Е ре м е н ко Та ть я на " , Воз ра ст = 22 , К ури тЛ и = t ru e } ,
ne w {И мя = " По г ре б и ц ки й О ле г ", Во зра ст = 4 2, К ур ит Ли = tr ue }
};
// До ст уп к э ле м е нт у ма сс ив а Сот р у дни ки м оже м име ть чере з е г о ин де к с:
va r t = Сот р у дни ки [2 ];
// Стр ои м LI NQ -за пр ос к ма сс ив у со тр у дни к ов ; в ы би ра ем т ех , в оз ра с т
// к от оры х б оль ш е 3 3 лет :
// va r С пи со к Взр о слы хС от ру д ни ков = fr om Сот р у дни к in Сот ру д ни ки
//
w her e С отр у дни к .В оз ра ст > = 3 3
//
o rde rb y Сот ру д ни к.И мя
//
s ele ct С отр у дни к ;
// И з ма с сив а с отр у дн и ков с оз да е м сл ов а рь сот р у дни к о в , в к от ор ом
// к л юч ом яв ляе т ся и мя с отр у дн ик а :
va r Сл ов а рь С отр у дни к ов = С отр у д ник и. T o Di cti o na r y( К л юч = > Кл ю ч.И мя) ;
// В эт ом с л у ча е оч е нь у д обны м ст а нов ит с я до ст у п к св еде ния м о
// с отр у дн ик е по е г о и мен и:
B oo le a n Ку ри тЛи Зи б о ров = С лов а р ь Сот ру д ни ков [" Зи бо р ов В и кто р "]. К ури т Ли ;
i nt Во зра ст З иб ор ов а = С лов а рь С о тру д ни ков [" Зи бо ров В икт ор "] .В оз ра ст ;
C on so le .Wr it e Li ne (" Со тр у дни к у Зи бор ов у В и кто р у - { 0 } лет \ n ",
В оз ра с тЗ ибо ров а );
// Стр ои м LI NQ -за пр ос к сл ов а рю со тр у дни к ов ; в ы би ра ем т ех , в оз ра с т
// к от оры х б оль ш е 3 3 лет :
va r Спи с ок Вз ро слы хС от ру д ни ков =
f rom С отр у дни к i n Сл о в а рь С отр у дни к ов
w he re Сот р уд ни к.V a l u e.В оз ра ст > = 3 3
o rde r b y С от ру дн и к.V a l ue .Им я
s e le ct ne w
{
Сот р уд ни к. Ke y,
Сот р уд ни к.V a l ue. В о зра ст ,
Ле т И ли Г од а = Со тр у дни к .V a l ue .В оз ра с т - 1 0 F *
M a t h. Tr u n ca te (С от ру дн ик .V a lu e. Во зра ст / 1 0F ) > = 5
};
// Вы в о д ре з уль та та за п ро са на к он со ль :
C on so le .Wr it e Li ne (" Спи с о к со тр у д ник ов , ста р ш е 3 3 лет : ") ;
f or e a c h ( va r x i n Сп ис о кВ зр ос лы хС отр у дни к ов )
C o ns ol e . W rite Li ne (" { 0} , в озра ст - { 1} { 2} " , x.K e y, x . Воз ра ст ,
x . Ле тИли Го да ? "л ет " : " г од а " );
C on so le .R e a d Ke y () ;
12
}
}
}
Представленный текст программы очевиден. Вначале задаем массив сотрудников
учреждения, в этом массиве всего 6 элементов. В комментарии показано, как можно организовать LINQ-запрос к заданному массиву. Далее массив конвертируем в словарь сотрудников, задавая в качестве ключа имя сотрудника. Затем организуем LINQ-запрос к словарю
Di ct io na r y , выбираем в новую коллекцию (список) тех, чей возраст превышает 33 года. Учитываем, что при выводе на консоль списка выбранных сотрудников мы говорим "47 лет", но
"34 года". То есть если из возраста вычесть число, кратное 10, то при остатке меньше 5 говорят, например, "34 года", а при остатке больше или равном 5 говорят "47 лет". Число,
кратное 10, мы вычисляем, используя функцию Ma t h. T ru n ca t e , которая возвращает целую
часть числа, поданную на ее вход. В этом алгоритме мы использовали булеву переменную
ЛетИ ли Г ода , которая определяет (по принципу "да" или "нет") следует писать "лет" или
"года".
Результат работы программы показан на рис. 19.4
Рис ун о к 1 9. 4  За п ро с к с лов а р ю да н ны х н а "в зр о слы х " со тр у дн ик ов
Убедиться в работоспособности программы можно, открыв решение Li nq Di c tio na r y .s l n папки Li nq Di ct io na r y .
5.5 Создание XML-документа методами классов пространства
имен System.Xml.Linq
Кроме пространства имен S y ste m. Xml , содержащего классы для обработки XMLдокументов, в Visual С#2010 имеем пространство имен S y stem . X ml. Li n q , содержащее классы, которые позволяют легко и эффективно изменять документы XML, а также организовывать LINQ-запросы. В данном примере оформим сведения о наших повседневных телефонных контактах в XML-документ. Этот документ будет иметь интуитивно понятную структуру: имя контакта, домашний и мобильный телефоны. Создав такой XML-документ и получив соответствующий XML-файл, его очень удобно просмотреть в MS Excel в виде таблицы, содержащей три столбца: имя контакта, домашний телефон и мобильный. Попутно
обсудим структуру XML-документа.
Итак, запустим среду Visual Studio 2010, выберем проект шаблона Console Application, укажем имя Name — L in qС оз да т ь XM L - до к ум ент . Затем на вкладке программного
кода введем текст, представленный в листинге 19.5.
Л ис ти н г 1 9 .5. С оз д ани е X ML - до ку ме н т а п р едс та в ля ю щ е г о т е л еф он ную кн и гу .
//
//
//
//
П ро г ра м ма с оз да е т типи чны й XM L - до к ум ент. С ее п о мощ ь ю м ожн о ра з обра ть с я в
стр у кт ур е XM L -д о к ум е нта . В ко мм ента ри ях прив ед ена тер мин ол о гия с о де ржи мо г о
X M L- д о к уме нта : ко рне в о й эл е ме нт, в л о женны е э ле менты , и м я э ле мента и е го
зн а че ние , а та кж е а триб уты э ле мента , и х и мена и зна чен ия.
13
// X M L- д о к уме нт п ре д ста в ляе т те ле фо нн у ю кн и г у, с о дер жа щ ую имя к онт а к та , но ме р
// до ма ш не г о те л е ф о на , а та кж е м оби ль н о г о. Пр о гра м ма п о сле со з да ни я XM L - до к ум е нта
// о тоб ра ж а е т е г о на ко нс о ли , а та кже за п исы в а е т е г о в фа йл . Е сл и эт от фа й л от кры ть
// с п ом ощ ь ю M S E x ce l, то мы по л уч им та б л иц у из тре х ст о лб цов .
us i ng S ys te m ;
us i ng S ys te m .X ml . Li nq ;
// Др у г ие ди ре ктив ы us i ng у да ле ны , п о с ко ль к у о ни н е и сп о ль з у ют ся в да нн ой пр о гра мме
na me spa ce Li nq Со зд а т ь XM L _ до к у мент
{
c la s s P ro gra m
{
sta ti c v oi d Ma i n( stri n g[] a rg s)
{
C on so le . Tit le = "К орне в ой э ле мент X ML - до к у мента " ;
// Со з да е м н ов ы й X ML - до к у мент :
X D oc u me nt X ML д о ку ме н т = ne w X D oc u m e nt(
// К о мме н та рий в XM L - до к ум ен те:
new X Co mme nt( " Те ле фон на я _ кни га - э то к орнев ой э ле мент X M L -д о к уме нта : "),
new XE leme n t( " Те л е ф онна я _ кн и га " , // - и м я ко рнев о го э лем ента
new XC om me nt( "Э ле ме нт С ТР ОКА со де рж ит а т риб ут К онта кт и дв а в л оженн ы х э ле ме нта ") ,
new XE leme nt( " С ТРО КА ", // - им я ( Na m e) эле мен та
n ew XAt tri bu te ( "К о нта к т" , "О ле г ") ,
n ew XE le me nt( "Д о ма ш ни й _те леф он " , " 2 3 6 - 2 3 -6 7 ") , / / - и мя э лем ента и е г о зна чен ие
n ew XE le me nt( " Мо б иль ны й _те леф он " , " + 7( 4 9 5) 62 5 - 3 1- 4 3 ")) ,
new XC om me nt( "Ат р иб у т К он та к т и мее т з на чен ие ' Пр о гн оз по г од ы ' : ") ,
new XE leme nt( " С ТРО КА ",
n ew XAt tri bu te ( "К о нта к т" , " Пр о гн оз по г о ды ") , // - а тр иб ут эл е мента С ТР ОК А
n ew XE le me nt( "Д о ма ш ни й _те леф он " , " 0 0 1" ),
n ew XE le me nt( " Мо б иль ны й _те леф он " , " ")) , / / - и мя э лем ента и е г о за че ние (V a l ue )
new XC om me nt( " По с ко ль к у ка ж ды й э ле ме нт К онт а к т и мее т а т р ибу т и дв а в лож е нны х = > "),
new XE leme nt( " С ТРО КА ",
n ew XAt tri bu te ( "К о нта к т" , " Бо ри с Гри г ор ь ев ич ") , / / - и мя а три бута - К онта кт
n ew XE le me nt( "Д о ма ш ни й _те леф он " , " 4 0 2 - 1 2 -4 5 ") ,
n ew XE le me nt( " Мо б иль ны й _те леф он " , " + 7( 4 9 5) 53 6 - 7 9- 9 4 ")) ,
new XC om me nt( " = > эле ме н та , в MS E x ce l ото бра зит ся та б ли ца с т ре мя к ол о н ка ми "),
new XE leme nt( " С ТРО КА ",
n ew XAt tri bu te ( "К о нта к т" , " Св ета ") , // - зна ч ение а тр иб ута - Св ета
n ew XE le me nt( "Д о ма ш ни й _те леф он " , " " ),
n ew XE le me nt( " Мо б иль ны й _те леф он " , " + 7( 4 9 5) 61 5 - 2 4- 4 1 ")))
);
// Со хра нить X ML - до к у мент :
X M Lд о к уме нт .Sa ve ( @ "C : \ Зиб ор ов . X ML ") ;
C on so le .Wr it e Li ne (X M L до к ум ент ) ;
C on so le .R e a d Ke y () ;
}
}
}
Чтобы понять текст программы, рассмотрим структуру полученного XML- файла, а
для этого откроем этот файл с помощью Internet Explorer (рис. 19.5).
Здесь весь XML-документ вложен в так называемый корневой элемент между
начальным тегом < Те ле ф он на я _ кни га > и конечным тегом </ Те л ефо нна я _ кн иг а > . Четыре
14
элемента С Т РО КА вложены в корневой элемент. В соответствующей таблице MS Excel элементы С ТР ОКА будут представлять строку в таблице. В свою очередь элемент С ТРО КА содержит в себе атрибут Конта к т и два вложенных в него элемента, имена (Name) которых—
Дом а ш ни й_ те л е ф он и Моб иль н ы й _те ле фон . Именно поэтому в MS Excel отобразится таблица с тремя колонками (один атрибут и два элемента): "Контакт", "Домашний_телефон" и
"Мобильный_телефон".
Элемент может иметь один или несколько атрибутов (а может и не иметь, как, скажем, элемент Д ома ш ний _те ле фон ), например, первый элемент С ТРО КА имеет атрибут с
именем (Name) Ко нта к т и со значением атрибута (Value) — 0 0 1 .
После запуска данной программы будет выведено на консоль содержимое XMLдокумента (без XML-объявления), а также будет создан XML-файл. Открыв этот файл с помощью MS Excel, получим таблицу телефонных контактов (рис. 19.6).
Рис ун о к 1 9. 5  XM L -ф а йл , от кр ы ты й в I nter net E x pl ore r
15
Рис ун о к 1 9. 6  XM L -ф а йл , от кр ы ты й в M S E xc el
Убедиться в работоспособности программы можно, открыв решение L i nqС о папки Li n qС оз да ть X ML - до к у мент .
зда ть X M L- д о ку ме н т .s l n
5.6 Извлечение значения элемента из XML-документа
В данном примере, решая задачу, мы получили строку XML-данных, например от
удаленной Web-службы, обеспечивающей прогнозом погоды. В этой текстовой XML-строке
содержатся метеорологические показатели на заданный нами район для текущей даты. В
данной задаче мы извлекаем из этих XML-данных только значение температуры.
Несколько слов о структуре XML-документа (рис. 19.7).
16
Рис ун о к 1 9. 7  Со де р ж им ое XM L - фа й ла с м етео ро ло г иче с ки ми п ок а за те ля ми
Как видно, XML-документ начинается с XML-объявления (XML declaration), в котором содержится информация о версии (version information parameter). А далее весь XMLдокумент состоит из вложенных друг в друга элементов. Элемент — это блок разметки
между начальным тегом, например <Г ор о д > , и конечным тегом </ Го ро д > . Самый внешний
элемент, в данном случае — это тег <М ете о ро ло ги че с кие По ка за т ели > , его называют корневым элементом (root element). Как видите, этот корневой элемент содержит в себе все показатели, и, таким образом, глубина вложенности этой иерархии равна двум. Вообще говоря, глубина вложенности такого XML-дерева может быть практически любой.
Итак, задача поставлена, сущность XML-данных понятна, приступаем к решению задачи. Для этой цели после запуска Visual Studio 2010 выберем проект шаблона Windows
Forms Application, укажем имя Name — L i nq 3 . Далее, попав в конструктор формы, из панели элементов Toolbox (Панель элементов) перетащим текстовое поле TextBox для вывода
в него строки с данными XML и значения температуры из соответствующего элемента
XML-дерева. Поскольку мы предполагаем вывод в текстовое поле не одной, а нескольких
строчек, в свойствах объекта te xtB ox 1 укажем tr ue напротив свойства Mu lti li ne . Затем на
вкладке программного кода введем текст, представленный в листинге 19.6.
Л ис ти н г 1 9 .6. Из в л еч е ни е з н ач е ния э л ем ен та из X ML -д ан ны х
// Да на стр о ка XM L , с од е рж а щ а я пр ог но зн ы е ме тео ро л о гич ес к и е по ка за те ли д ля
// г. М о скв ы на за да н ну ю да т у . Пр о гра мма изв л ек а ет из к ор нев о г о э ле мен та
// X M L- д о к уме нта зна че ни е те мпе ра т уры э лем ента " Т емп ера т у р а " :
us i ng S ys te m .W in do w s .F or ms ;
//Др у гие дире к тив ы u si ng у да ле ны , по с ко л ь к у они не и спо ль зу ю тся в да н ной п ро гр а м ме
na me spa ce Li nq 3
{
p ubl i c p a rti a l cl a s s Fo rm 1 : F or m
{
p u bli c F or m1 ()
17
{
I nit ia l ize Com po ne nt() ;
t his . Te xt = " LI NQ - за пр о с к X ML - да нны м " ; t ext Bo x 1. M ult il ine = t ru e;
st ri ng Ст ро ка XM L =
@" < ? xml ve r sio n = " " 1. 0 " "? >
< Ме т е о ро ло г иче с кие По ка за те ли >
< Го ро д > Мо с кв а </ Го ро д >
< Да та > 2 01 0. 0 5 .1 5 0 6 : 3 0 U T C< /Д а та >
< Те мп е ра т ура > 6 4 F ( 1 8 C) </ Те мпер а т ура >
< Ве те р >Се в -В ос т 8 м/ се к </В ете р>
< Ви ди мо ст ь > 1 2 км < /Ви ди м ос ть >
< Вла ж но ст ь > 7 2 % </В ла ж но сть >
< Да в ле ние > 7 60 м м рт ст < /Да в л ение >
< /Ме те о ро л о ги че с кие По ка за те ли > " ;
// За гр у з ка к орне в о г о эле мен та и з ст ро к и, с о держ а щ ей XM L :
va r Ко рне в ой Эле ме нт = S yst em .X m l. Li nq . XE le me nt. Pa r se( Стр ок а X M L) ;
// И ли ко рне в ой э ле ме нт X ML - до к ум ента по л уч а ем че р ез фа й л:
// За п ис ы в а е м стр о к у, с о дер жа щ у ю XM L в фа й л:
// S ys te m .IO . Fi le . Wr ite A ll Te xt( " По к а за те ли По г о ды . xml " , Стр ок а X M L) ;
// За гр уж а е м к орн е в о й эле мен т X ML :
// va r Ко рне в ойЭ ле ме нт = S yst em .X ml .L i nq.
//
XE l eme nt .L oa d(" П ок а за т ели П о го ды .xm l ") ;
// И з к орн е в о го э ле м е нта изв ле ка ем в ло женны й в не го эле мен т
// " Те мпе ра т ура " и п о лу ча е м с оот в етс тв у ющ ее зна чени е (V a l ue ) это г о
// э ле ме нта :
st ri ng Те м пе р а т ура = К ор нев о йЭ л емент .E l eme nt( " Те мп е ра т ура ") .V a l ue ;
te xtB ox 1 . Te x t = "Ст ро ка X M L: \r\ n\ r\ n " + Ст ро ка X ML + " \r\ n\r\ n " ;
te xtB ox 1 . Te x t + = "З на ч ение те мпе ра т уры = " + Те мп ер а ту ра ;
}
}
}
В начале текста программы задаем текстовую строку, содержащую XML- данные. Далее,
используя метод Pa r se класса X E le m en t пространства имен Li nq , получаем корневой элемент
XML-документа. В комментарии показано, как можно получить корневой элемент через запись/чтение XML-файла. Затем с помощью метода E leme nt извлекаем значение (V a lu e ) элемента температура, которое выводим в текстовое поле.
Фрагмент работы программы приведен на рис. 19.8.
Рис ун о к 1 9. 8  И зв л е чени е з на че ния э ле м ента и з X ML - до к у мент а
18
Рис ун о к 1 9. 9  Пре д с та в лен ие X ML - да нны х в в и д е та б ли цы в M S E x cel
Убедиться в работоспособности программы можно, открыв решение Li n q3 .s l n папки
Li nq 3 .
Теперь решим похожую задачу по извлечению значения элемента, но пусть XMLданные представлены в другой форме, а именно каждый метеорологический показатель
вложим в один и тот же элемент < По ка за тель > < /П о ка за т ель > , в этом случае глубина
вложенности элементов будет уже равна трем (см. листинг 19.7). Естественно спросить: что
мы будем с этого иметь? Дело в том, что если соответствующий XML-файл открыть с помощью табличного редактора MS Excel, то мы сможем увидеть эти XML-данные в виде
наглядной таблицы, даже не ссылаясь на таблицу стилей — файл XSLT (не путать с XLSфайлом), см. рис. 19.9.
Теперь для получения значения температуры удобно воспользоваться типовым
LINQ-запросом (листинг 19.7).
Л ис ти н г 1 9 .7. Из в л еч е ни е з н ач е ния э л ем ен та из X ML -д ан ны х
// Да на стр о ка XM L , к ото ра я с о дер жит пр о г ноз ны е мете ор о ло ги ч ес кие п ок а з а те ли дл я
// г. М о скв ы на за да н ну ю да т у . Пр и это м к а жды й м ете ор ол о ги че с кий по ка за те ль в л ожен
// в о дин и т от ж е э л е ме нт <П о ка за тел ь > </ По ка за те ль >. Эт о о бесп еч ив а ет у д обны й
// пр о см от р со отв е тс т в у ющ е г о XM L -фа йла в M S E x cel в в и де та б л ицы . Пр о гра мма на х о дит
// в к орне в о м эле ме н те да нн о го X M L - д о к ум ента эл еме нт " Те мпе р а ту ра " и и зв ле ка ет и з
// не г о зна ч е ние те м пе ра т ур ы .
us i ng S ys te m .W in do w s .F or ms ;
us i ng S ys te m . Li nq ;
// Др у г ие ди ре ктив ы us i ng у да ле ны , п о с ко ль к у о ни н е и сп о ль з у ют ся в да нн ой пр о гра мме
na me spa ce Li nq 4
{
p ubl i c p a rti a l cl a s s Fo rm 1 : F or m
{
p u bli c F or m1 ()
{
I nit ia l ize Com po ne nt() ;
t his . Te xt = " LI NQ - за пр о с к X ML - да нны м " ; t ext Bo x 1. M ult il ine = fa l se ;
// И ни циа ли з а ци я XM L - стр о ки :
st ri ng Ст ро ка XM L =
@" < ? xml ve r sio n = " " 1. 0 " "? >
< Ме т е о ро ло г иче с кие По ка за те л и >
< По ка за те л ь >
< Го ро д > Мо с кв а </ Го ро д >
</ П ок а за т е ль >
19
< По ка за те л ь >
<Да та > 20 1 0. 0 5. 1 5 0 6 : 3 0 U TC < / Да та >
</ П ок а за т е ль >
< По ка за те л ь >
< Те мпе ра тур а > 6 4 F ( 1 8 C) </ Т емпе ра т ура >
</ П ок а за т е ль >
< По ка за те л ь >
<В е те р > С е в -В о ст 8 м/ се к </ Вет ер >
</ П ок а за т е ль >
< По ка за те л ь >
<В и дим о с ть > 1 2 к м </В ид им о сть >
</ П ок а за т е л ь >
< По ка за те л ь >
<В ла ж но с ть > 7 2 % </ Вла жно сть >
</ П ок а за т е ль >
< По ка за те л ь >
<Да в ле н и е > 7 6 0 мм рт с т </Да в лени е >
</ П ок а за т е ль >
< /Ме те о ро л о ги че с кие По ка за те ли > " ;
va r Ко рне в ой Эле ме нт = S yst em .X m l. Li nq . XE le me nt. Pa r se( Стр ок а X M L) ;
// И ли ко рне в ой э ле ме нт по л уча е м чере з фа й л :
// За п ис ы в а е м стр о к у, с о дер жа щ у ю XM L в фа й л:
// S ys te m .IO . Fi le . Wr ite A ll Te xt( " По к а за те ли По г о ды 2 . xml " , С тр о ка XM L) ;
// За гр уж а е м к орн е в о й эле мен т:
// va r Ко рне в ойЭ ле ме нт = S yst em .X ml .L i nq. XE leme nt . Lo a d(
//
" По ка за те лиП о г оды 2 .x ml ") ;
// За п ро с - э то к ол ле к ция ( спи с о к ) с тр ок , к у да изв ле ка ем зна чение
// (V a l ue ) э л е ме нт а " Те м пера т ура " :
va r За п ро с = f ro m x i n К орнев ой Эл емент .E l eme nt s( "П о ка за те ль " )
f ro m y i n x .E le me nts (" Т е мпер а т ура ")
se l e ct y .V a lu e ;
// Та к их с тр ок в к ол ле к ции За пр о с - о дна
te xtB ox 1 . Te x t = "З на ч е ние те мпе р а ту ры = " ;
f or e a c h ( va r x i n За пр ос )
te xt Bo x 1. Te xt = te xtB o x1 . Te xt + x ;
}
}
}
Как видно из программного кода, поиск организован в двух уровнях (два предложения fr om ), сначала выбор в коллекцию всех элементов По ка за те ль , а затем из этой
коллекции поиск элементов Те мпе ра т ур а . Результат запроса записывается в коллекцию
строк, где имеем ровно одну строку. Фрагмент работы программы показан на рис. 19.10.
Рис ун о к 1 9. 1 0  LI NQ -за п ро с к XM L - д о к уме нту
Убедиться в работоспособности программы можно, открыв решение Li nq 4 .sl n из
папки L in q 4 .
5.7 Поиск строк (записей) в XML-данных с помощью LINQ-запроса
Имеем XML-данные, в которых содержится традиционная для нашей книги таблица с
именами и телефонами, причем имена в этой телефонной табличке повторяются, например,
строка с именем "Витя" содержит мобильный телефон, а потом по мере знакомства с этим
Витей у нас появился уже и его домашний телефон. Задача состоит в том, чтобы в данной
20
таблице телефонов (представленной в виде XML, см. листинг 11.8) найти все строчки с
именем "Витя". Эта маленькая несерьезная, на первый взгляд, задача подразумевает, например, такую уже "серьезную" задачу. Имеем громадную базу данных, которую мы получили
на каком-то этапе обработки в виде XML, и нам требуется "отфильтровать" записи в этой
базе на предмет содержания в некотором поле определенной строки.
Прежде чем решать данную задачу, давайте посмотрим отображение обсуждаемых
XML-данных в табличном редакторе MS Excel (рис. 19.11).
Рис ун о к 1 9. 1 1  О тоб ра жени е XM L - да нны х в M S E x cel
Как видно, в редакторе MS Excel наши XML-Данные представлены весьма наглядно.
И очень понятно, что мы хотим получить, а именно, все номера телефонов напротив имени
"Витя".
Для решения этой задачи запустим Visual Studio 2010 и выберем проект шаблона
Windows Forms Application, укажем имя Name — Li nq 5 . Далее, попав в конструктор формы, из панели элементов Toolbox перетащим текстовое поле TextBox для вывода в него
найденных строк из таблицы XML. В свойствах текстового поля разрешим ввод множества
строк (а не одной), для этого свойство M u lti l ine переведем в состояние tr ue . Затем на вкладке программного кода введем текст, представленный в листинге 19.8.
Л ис ти н г 1 9 .8. Из в л еч е ни е з н ач е ния э л ем ен та из X ML -д ан ны х
// Им еем XM L -да нны е , в к от оры х со де ржа т ся та б ли ца с им ена м и и те ле ф она м и, пр иче м
// и мена в это й те ле фон но й та б ли ч ке пов тор яю тс я. За да ча с о с тоит в т о м, чт обы в
// да нн ой та б ли це те ле ф он о в (пре д ста в ле нной в в ид е XM L) на й ти в се ст ро ч ки c
// и мене м "В итя " с п о мощ ь ю L I NQ -за п ро са .
us i ng S ys te m . Li nq ;
us i ng S ys te m .W in do w s .F or ms ;
// Др у г ие ди ре ктив ы us i ng у да ле ны , п о с ко ль к у о ни н е и сп о ль з у ют ся в да нн ой пр о гра мме
na me spa ce Li nq 5
{
p ubl i c p a rti a l cl a s s Fo rm 1 : F or m
{
21
}
p u bli c F or m1 ()
{
I nit ia l ize Com po ne nt() ;
t his . Te xt = " LI NQ - за пр о с к X ML - да нны м " ; t ext Bo x 1. M ult il ine = t ru e;
// И ни циа ли з а ци я XM L - стр о ки :
st ri ng Ст ро ка XM L =
@ " <? xm l ve rsi on = " " 1. 0 " " ?>
< Т а б л и ца Те ле ф он ов >
< Стр о ка >
<И ме на > Витя </ И ме на >
< Но ме ра _ те ле фо нов > 2 7 4 2 8 4 4 </ Но ме ра _ тел еф он ов >
</ Стр о ка >
< Стр о ка >
<И ме на > Анд ре й </ И ме на >
< Но ме ра _ те ле фо нов > 8 - 08 5 - 4 56 -2 3 7 8 </ Но мер а _ тел е фон ов >
</ Стр о ка >
< Стр о ка >
<И ме на > Ка ра п у зов а Та ня < /Им ена >
< Но ме ра _ те ле фо нов > 4 4 5 - 5 6 - 47 </ Но ме ра _ тел еф он ов >
</ Стр о ка >
< Стр о ка >
<И ме на > Витя </ И ме на >
< Но ме ра _ те ле фо нов > 0 9 9 7 2 1 6 1 5 2 </ Но мера _ тел еф онов >
</ Стр о ка >
< Стр о ка >
<И ме на > Ни кип е л ов </И мена >
< Но ме ра _ те ле фо нов > 2 3 6 - 7 7 - 76 </ Но ме ра _ тел еф он ов >
</ Стр о ка >
< Стр о ка >
<И ме на > Зиб ор ов </И мена >
< Но ме ра _ те ле фо нов > 2 5 4 6 7 9 7 </ Но ме ра _ тел еф он ов >
</ Стр о ка >
< / Та б ли ца Те ле ф он ов > ";
va r Ко рне в ой Эл е ме нт = S yst em .X m l. Li nq . XE le me nt. Pa r se( Стр ок а X M L) ;
// За п ис ь стр ок и, с о де р жа щ ей XM L в ф а йл :
// S ys te m .IO . Fi le . Wr ite A ll Te xt( " Та б ли ца Те ле фон ов .x ml ", Стр ок а X M L) ;
// va r Ко рне в ойЭ ле ме нт = S yst em .X ml .L i nq.
//
X E le m en t. L oa d (" Та б ли ца Те ле фо нов . xml ") ;
va r За п ис и =
fr o m x i n Ко рне в ойЭ ле м ент .E leme nt s( " С тр ок а ")
w he re ( str in g) x.E leme nt (" Имена ") = = "Ви тя "
se le ct x .E le me nt( "Н о мера _те ле фо нов ") .V a l ue ;
te xtB ox 1 . Te x t = te xt Bo x 1. Te xt +
@ "С тро ки , с о держа щ ие и мя " "В итя " ": " + " \r \n " ;
// Вы в о д ко л ле к ции за п и сей в те к ст ов ое п оле te xt Bo x 1:
f or e a c h ( va r x i n За пи си )
te xt Bo x 1. Te xt = te xtB o x1 . Te xt + x + " \r\ n " ;
// Та к их за п исе й в эт ой к ол ле к ци и - р ов н о о д на
}
}
Как видно, в начале программы мы инициализируем (т. е. присваиваем начальные
значения) XML-строку. Далее извлекаем корневой элемент из XML-документа, он, по сути,
отличается от XML-документа отсутствием XML-объявления (в этом можно убедиться в
отладчике программы). В комментарии указано, как можно получить корневой элемент в
том случае, если он представлен в виде XML-файла во внешней памяти. Затем организуем
типовой, стандартный LINQ-запрос. Результат запроса попадает в коллекцию записей, которую выводим в текстовое поле, используя оператор цикла f or ea c h . Фрагмент работы программы показан на рис. 19.12.
22
Рис ун о к 1 9. 1 2  LI NQ -за п ро с к XM L - д о к уме нту
Убедиться в работоспособности программы можно, открыв решение Li n q 5. sl n из
папки L in q 5 .
5.8 LINQ-запрос к набору данных DataSet
Весьма полезной оказывается организация LINQ-запросов к наборам данных Da t a Se t ,
используемым, к примеру, при работе с базами данных. Объект класса Da ta Set представляет
расположенный в памяти кэш (cache) данных (кэш — это промежуточная память с быстрым
доступом, содержащая информацию, которая может быть запрошена с наибольшей вероятностью). Реляционные базы данных работают чаще всего с совокупностью таблиц. Каждая
из этих таблиц задается как объект класса Da ta Ta b le , один такой объект представляет ровно
одну таблицу данных. Набор данных Da ta S e t содержит в себе несколько объектов (таблиц)
Da ta Ta b le . Запросы LINQ к таблицам данных, кэшированным в объекте Da ta Set , упрощают
и ускоряют процесс отбора.
Данная задача состоит в том, чтобы создать программу, которая обеспечивает ввод
простейшей таблицы, содержащей два поля — название города и численность его населения. Программа способна фильтровать данные в таблице; будем производить отбор городов,
численность населения которых превышает миллион жителей.
Для решения этой задачи запустим Visual Studio 2010 и выберем проект шаблона
Windows Forms Application, укажем имя Name — L in q Г ор о да . Далее, попав в конструктор
формы, из панели элементов Toolbox перетащим элемент управления для отображения и редактирования табличных данных D a ta Gr idV i ew , две командные кнопки Button и текстовое
поле TextBox. Одна кнопка предназначена для команды сохранения данных, другая — для
поиска данных в таблице, а текстовое поле — для вывода в него найденных строк из таблицы. В свойствах текстового поля разрешим ввод множества строк, для этого свойство M ult ili ne переведем в состояние true. Затем на вкладке программного кода введем текст, представленный в листинге 19.9.
Л ис ти н г 1 9 .9. Из в л еч е ни е п о л ей из на бо ра д ан ны х Da t aS e t
// В д а нн ой пр ог ра мм е э кр а нна я ф ор ма с о д ержит э ле мент упра в лени я д ля от обра ж ен ия
// и ре да кти ров а ния та б ли чны х да н ны х Da ta G rid V iew , дв е к о ма н дны е кно п ки и те к ст о в ое
// п оле . Пр и ста рте п ро гра м мы , е сли е сть со отв е тс тв ую щ ий фа й л XM L , т о п ро г ра м ма
// о тоб ра ж а е т в Da t a Gr idV ie w та бл и ц у го р од ов - на зв а ние г ор о да и чи сле нн ос ть
// на се лени я. П ри щ е лч ке на кн оп ке " Со хр а нить " в се из мене ния в та б ли це за пи сы в а ю т ся
// в XM L - фа йл . Пр и щ е лч ке на в то ро й кн оп ке " На йт и " в ы п ол няет ся L I NQ -за п ро с к на б ору
// да нны х Da ta Se t на пои с к г ор о дов -м ил ли онер ов в и с ко м ой та б ли це . Р ез уль та т за п р оса
// в ы в од ит ся в те к ст о в ое п о ле .
us i ng S ys te m ;
us i ng S ys te m .C oll e c ti o ns . Ge ne r i c;
us i ng S ys te m .C omp o n e nt Mo de l ;
us i ng S ys te m . Da ta ;
us i ng S ys te m . Dra w in g ;
us i ng S ys te m . Li nq ;
us i ng S ys te m . Te xt ;
23
us i ng S ys te m .W in do w s .F or ms ;
// Др у г ие ди ре ктив ы us i ng у да ле ны , п о с ко ль к у о ни н е и сп о ль з у ют ся в да нн ой пр о гра мме
na me spa ce Li nq Го ро д а
{
p ubl i c p a rti a l cl a s s Fo rm 1 : F or m
{
Da ta Ta ble Та б л ица = ne w Da ta Ta b le( ); // Со зд а ние об ъе кт а та б ли ца да н ны х
Da ta Se t На б о рД а нны х = ne w Da ta Set( ); // Со зд а ние об ъе кт а на б ор да н ны х
p u bli c F or m1 ()
{
I nit ia l ize Com po ne nt() ;
ba se . T e xt = " LI NQ -за пр ос к на бо р у да н ны х Da ta Set " ;
b utt o n1 . Te xt = " Со хра н ить " ; b ut to n 2. Te xt = " На йти " ;
te xtB ox 1 .M u l tili ne = t ru e ;
i f ( S y ste m .I O .F ile .E xis ts( " Го ро да . x ml" ) = = fa lse )
{
// Е сл и X ML - фа й ла НЕ Т :
// За п олн е ние "ш а п ки " та б ли ц ы
Та б ли ца .C ol um ns .A dd( " Го ро д ") ; Та б л и ца .C ol um n s.A dd (" На сел ение ") ;
// Д об а в и ть об ъе кт Та б ли ца в Da ta Set
На б о рДа н ны х. T a bl e s .A d d( Та б ли ца ) ;
d a ta Gr idV i e w 1 . Da ta So u rc e = Та б ли ца ;
}
el se / / Е сл и XM L -фа йл Е C Т Ь :
{
На б о рДа н ны х. R e a d Xm l( "Г ор о да . xml ") ;
// С о де рж имо е Da ta Set в в ид е с тро ки X M L д ля от ла д к и:
// s tri ng С тро ка XM L = На бо рДа нны х . Get Xm l() ;
Та б ли ца = На б орД а нны х. Ta ble s[ "Г ор о да " ];
d a ta Gr idV i e w 1 . Da ta Memb er = " Г ор ода " ;
d a ta Gr idV i e w 1 . Da ta So u rc e = На борД а нны х ;
}
}
p ri va te vo id b utt on 1 _C li c k( ob je ct se nd er, E v en tAr gs e)
{
// Щ е л чо к м ы ш ь ю на кн оп ке " Со х ра нить " - с ох ра ни ть фа й л Го ро да .x ml :
Та б л и ца . Ta bl e Na me = " Го ро да " ;
На б ор Да нны х . Wri te Xml( " Го ро да . x ml" ) ;
}
p ri va t e vo id b utt on 2 _C li c k( ob je ct se nd er, E v en tAr gs e)
{
// Щ е л чо к м ы ш ь ю на кн оп ке " П ои с к" - за пр ос го ро д ов - мил ли оне ров :
te xtB ox 1 .C le a r() ; // - о чи ст ка те к с тов о г о по ля
va r Го ро да М лн = f ro m Го ро д i n Та бли ца .A sE n u mera ble ( )
w he re Co n ve r t. T oI nt 3 2( Го ро д .
Fie ld < Str i ng >( " На с еле ние ")) > = 1 0 00 0 0 0
s e le ct ne w
{
A = Го ро д . Fie l d <s tr in g >( " Г ор о д" ),
B = Г оро д . Fie ld < str in g >( " На се лен ие ")
};
te xtB ox 1 . Te x t = te xt Bo x 1. Te xt + " Г ор ода - ми лли оне ры :\r \n " ;
// Вы в о д ре з уль та та за п ро са в те к ст ов ое п оле te xt Bo x 1:
f or e a c h ( va r Го ро д i n Го ро да Млн )
te xt Bo x 1. Te xt = te xtB o x1 . Te xt + Г ор од .A + " - " + Г ор од .B + "\r \ n" ;
}
}
}
24
В начале программы создаем объекты классов Da ta Se t и Da ta Ta b le так, чтобы они
были видимыми из всех процедур класса F o rm 1 . Далее сразу после инициализации компонентов экранной формы (т. е. после выполнения процедуры I ni tia l i zeC omp o ne nt ) проверяем,
существует ли файл Г ор ода . xml , куда мы записываем искомую таблицу. Если файл не существует, т. е. пользователь первый раз запустил нашу программу, то мы создаем таблицу,
состоящую из двух полей (колонок): "Город" и "Население", добавляем (A dd ) эту таблицу в
набор данных, а также указываем таблицу в качестве источника данных (Da t a S o ur ce ) для
сетки данных da ta G ri d V ie w 1 . Если же файл Г ор ода . xml уже создан, то мы читаем его в
набор данных Da ta Se t и из него заполняем таблицу данных, а также этот набор данных указываем в качестве источника для сетки данных.
При обработке события "щелчок мышью на кнопке Запись” программируем сохранение редактируемой таблицы в файле Го ро да . хm l . В процедуре обработки события "щелчок на кнопке" Найти организуем LINQ-запрос к заполненной пользователем таблице
Da ta Ta b le , являющейся представителем D a t a Set . Условием запроса является отбор таких
полей таблицы, где население превышает миллион жителей. Заметим, что если не задавать
условие wh e re , то в результате запроса получим все содержимое источника данных, т. е. все
строки таблицы городов. Результат запроса выводим в текстовое поле, используя цикл
foreach.
Фрагмент работы программы показан на рис. 19.13.
Убедиться в работоспособности программы можно, открыв решение Li nq Г ор ода . sl n
из папки Li nq Г ор о да .
Рис ун о к 1 9. 1 3  LI NQ -за п ро с к на б ор у да н ны х
5.9 Доступ к базе данных с помощью LINQ to SQL
В данном примере вначале создадим базу данных городов, содержащую два поля:
название города и численность его населения. Затем организуем доступ к этой базе данных
с помощью LINQ to SQL и создадим запрос на извлечение коллекции городов, численность
населения в которых превышает миллион жителей. Эту задачу можно было бы решить, организовав LINQ-запрос через набор данных Da ta set , как мы это делали в предыдущем разделе, однако мы хотим продемонстрировать и другой подход.
Вначале запустим Visual Studio 2010 и выберем проект шаблона Windows Forms
Application, укажем имя Name— L i nq T oS ql Гo po дa . Далее, попав в конструктор формы, из
панели элементов Toolbox перетащим элемент управления для отображения и редактирования табличных данных DataGridView, на этот элемент в конечном итоге будет попадать результат запроса.
25
Теперь создадим базу данных SQL Server. Для этого в меню Project (Проект) выберем команду Add New Item (Добавить новый элемент). В появившемся окне выберем элемент База данных, основанная на службах, а в поле Name укажем имя базы данных Г о ро да . md f . Далее в окне мастера настройки источника данных зададим тип модели базы данных — Набор данных. Затем согласимся на сохранение строки подключения в файле конфигурации приложения. Теперь после щелчка на кнопке Готово будет создан пустой набор
данных. Этот набор данных Го ро да .md f теперь будет виден в окне Solution Explorer (Обозреватель решений).
Чтобы заполнить этот набор данных, дважды щелкнем мышью по значку Города.mdf; таким образом, мы попадаем в окно Server Explorer/Database Explorer (Обозреватель серверов/Обозреватель баз данных). Здесь в контекстном меню узла Таблицы выберем
команду Добавить новую таблицу. В результате мы попадаем уже в другое окно —
dbo.Table1, где зададим имена двух столбцов: Город и Население (рис. 19.14).
Рис ун о к 1 9. 1 4  За ка з п ол ей т а бл и цы в ба зе да нн ы х
При сохранении (<Ctrl>+<S>) пустой таблицы появится запрос на выбор имени для
таблицы, здесь мы зададим имя Города.
Теперь будем заполнять сформированную таблицу. Для этого в Обозревателе серверов щелкнем правой кнопкой мыши на узле Города (имя нашей таблицы) и в появившемся
контекстном меню выберем команду Показать таблицу данных. Теперь в окне Города мы
имеем возможность заполнять нашу таблицу (рис. 19.15).
На этом этапе задача создания базы данных и заполнения в ней таблицы городов выполнена. Приступаем к организации запроса к таблице городов. Как уже указывалось ранее,
LINQ-запрос можно построить через набор данных Da ta Set , а можно LINQ-запрос организовать с помощью классов LINQ to SQL. Эти классы сопоставляются с таблицами и представлениями базы данных и называются классами сущностей DataContext. Класс сущности
сопоставляется с записью, а отдельные свойства класса сущности сопоставляются с отдельными столбцами, образующими запись. Сказанное, вероятно, звучит запутанно, но практически сводится к перетаскиванию мышью созданной нами таблицы Го ро да из окна Server
Explorer/ Database Explorer (Обозреватель серверов/Обозреватель баз данных) на’так
называемый Object Relational Designer (реляционный конструктор объектов). В результате
получим класс сущностей именно для нашей таблицы Г ор о да , наследованный от базового
26
класса Da ta C o nte xt , и в тексте нашей программы уже легко сможем строить LINQ-запросы,
обращаясь к объекту класса сущностей.
Чтобы получить в нашем проекте реляционный конструктор объектов, в меню
Project выберем команду Add New Item (Добавить новый элемент), а в появившемся одноименном окне — шаблон (элемент) LINQ to SQL Classes. В поле Name укажем имя файла
Сущ но ст и. dbm l и щелкнем на кнопке Add. Внешний вид реляционного конструктора объектов можно увидеть на рис. 19.16.
Теперь, как мы уже говорили, просто перетаскиваем мышью таблицу Г ор од а из окна
Server Explorer/Database Explorer (Обозреватель серверов/Обозреватель баз данных) на
реляционный конструктор объектов. Реляционный конструктор объектов создает классы и
применяет специфические для LINQ to SQL атрибуты, чтобы иметь функциональные возможности LINQ to SQL (возможности передачи данных и редактирования, какие имеются у
Da ta Co nte xt ). А нам остается всего лишь на вкладке программного кода ввести текст, представленный в листинге 19.10.
Рис ун о к 1 9. 1 5  За п о лнен ие та бл и цы го ро дов в ба зе да нны х
27
Рис ун о к 1 9. 1 6  Д об а в ле ни е в пр ое кт ре ля ци онн о го ко нс тр у кто р а об ъе кт ов
Л ис ти н г 1 9 .10 . О р г аниз а ция L IN Q -з а п р оса к баз е да нн ы х
// Да н ное W i ndo w s -п р ило ж е ни е со ст ои т и з эк ра нн ой ф ор мы и эл емент а упр а в ле ния
// Da ta Gr idV ie w . В пр о гра мме о р га ни зов а н LI NQ - за пр о с к б а зе д а нны х го ро д ов с
// п ом ощ ь ю б а зо в о г о кл а с са с ущ но сте й Da t a Co nte xt . Д ля эт о г о в да нн ую п ро гр а м му
// доба в ле н (P ro je ct | Add Ne w Ite m) э лем е нт (ш а бл он) " К ла с сы LI NQ t o SQ L ",
// Na me = С ущ н ос ти. db ml. П о сле св яз ы в а ния та бл и цы " Го ро да " из ба зы да нны х с
ба зов ы м
// кла с со м с ущ н о сте й (п уте м п е рет а с ки в а н ия мы ш ь ю та бли ц ы и з о кна E x pl orer / Da ta ba se
// E x pl ore r в о кн о к он стр у кт ора Ob je ct R e la tio na l Des ig ne r) а в то м а тиче с ки бы л
// со зд а н к ла с с С ущ н ос ти Da ta Co nte xt , п ро изв о дн ы й ( на сле д ов а нны й) от ба з ов а г о кл а с са
// Da ta C o nte xt . И сп ол ь зу я это т к ла с с в да н ной пр о гра мм е о р га н изов а н LI N Q - за пр о с к
// ба з е да нн ы х на по лу че н ие к ол ле к ци и ( с пис ка ) го ро д ов , ч ис л енно сть на се лени я в
// кот оры х пре в ы ш а е т ми л ли он ж ите лей . Р ез уль та т за пр о са в ы в еде н на э ле мент
// упра в лен ия Da ta Gri dV ie w .
us i ng S ys te m ;
us i ng S ys te m . Li nq ;
us i ng S ys te m .W in do w s .F or ms ;
// Др у г ие ди ре кт ив ы us i ng у да ле ны , п о с ко ль к у о ни н е и сп о ль з у ют ся в да нн ой
про г ра м ме
na me spa ce Li nq T o Sql Г ор ода
{
p ubl i c p a rti a l cl a s s Fo rm 1 : F or m
{
// С по м ощ ь ю о б ъе кта б а з ов о г о к ла с са Da ta Co nt ext б у дем иметь до ст уп к
// та б ли це б а зы да нны х :
p ri va te С ущ но ст иDa t a Co n te x t Б Д = ne w С ущ н о сти Da ta Co nt e xt() ;
// pr iva te Го ро да Da ta Se t
p u bli c F or m1 ()
{
I nit ia l ize Com po ne nt() ;
// В ре з у ль т а те за пр о са п ол у ча е м к ол ле к ци ю за п ис ей и з та б ли цы ба зы
// да н ны х , у дов ле тв о ря ющ ей ус л о в ию w here :
28
va r Го ро да М лн = f ro m г ор од а i n Б Д.Г ор о да
w he re Co n ve r t. T oI nt 3 2( г ор ода . На сел ение ) > 1 0 0 00 0 0
s e le ct г ор од а ;
// или s e le ct ne w { г ор о да . Г оро д , г ор ода . На сел ение } ;
// Ре з у ль та т за пр о са в ы в о ди м на э лем ент у пра в лени я D a ta G rid V iew ,
// от об ра ж а ющ и й та б ли чны е да н ны е:
da ta G ridV ie w 1. Da ta S o ur ce = Г ор о д а Млн ;
}
}
}
Фрагмент работы программы показан на рис. 19.17.
Рис ун о к 1 9. 1 7  За пр ос к ба зе да н ны х на г ор ода - ми лли оне ры
Убедиться
в работоспособности
qT o Sq l To po fla . sl n папки Li nq T o Sq l Г ор о да .
программы
можно,
открыв
решение
L i n-
6 Задания
1. Счет в банке представляет собой структуру с полями: номер счета, код счета, фамилия владельца, сумма на счете, дата открытия счета, годовой процент начисления. Поиск
по номеру счета, дате открытия и владельцу.
2. Запись о товаре на складе представляет собой структуру с полями: номер склада,
код товара, наименование товара, дата поступления на склад, срок хранения в днях, количество единиц товара, цена за единицу товара. Поиск по номеру склада, коду товара, дате поступления и сроку хранения (просроченные и не просроченные товары).
3. Запись о преподаваемой дисциплине представляется структурой: код дисциплины
в учебном плане, наименование дисциплины, фамилия преподавателя, код группы, количество студентов в группе, количество часов лекций, количество часов практики, наличие
курсовой работы, вид итогового контроля (зачет или экзамен). Зачет 0,35 ч на одного студента; экзамен — 0,5 ч на студента. Поиск осуществлять по фамилии преподавателя, коду
группы, наличию курсовой, виду итогового контроля.
4. Информационная запись о книге, выданной на руки абоненту, представляет собой
структуру следующего вида: номер читательского билета, фамилия абонента, дата выдачи,
срок возврата (количество дней), автор, название, год издания, издательство, цена. Поиск по
полям: номер читательского билета, автор, издательство, дата возврата (просроченные).
5. Информационная запись о файле содержит поля: каталог, имя файла, расширение,
дата и время создания, атрибуты «только чтение», «скрытый», «системный», признак удаления, количество выделенных секторов (размер сектора принять равным 512 байт). Поиск
выполнять по каталогу, дате создания, по признаку удаления.
6. Разовый платеж за телефонный разговор является структурой с полями: фамилия
плательщика, номер телефона, дата разговора, тариф за минуту разговора, скидка (в процентах), время начала разговора, время окончания разговора. Поиск по фамилии, дате разговора, номеру телефона.
29
7. Модель компьютера характеризуется кодом и названием марки компьютера, типом
процессора, частотой работы процессора, объемом оперативной памяти, объемом жесткого
диска, объемом памяти видеокарты, стоимостью компьютера в условных единицах и количеством экземпляров, имеющихся в наличии. Поиск по типу процессора, объему ОЗУ, памяти видеокарты и жесткого диска.
8. Список абонентов сети кабельного телевидения состоит из элементов следующей
структуры: фамилия, район, адрес, телефон, номер договора, дата заключения договора,
оплата установки, абонентская плата помесячно, дата последнего платежа. Поиск по фамилии, району, дате заключения договора, дате последнего платежа.
9. Сотрудник представлен структурой Person с полями: табельный номер, номер отдела, фамилия, оклад, дата поступления на работу, процент надбавки, подоходный налог,
количество отработанных дней в месяце, количество рабочих дней в месяце, начислено,
удержано. Поиск по номеру отдела, полу, дате поступления, фамилии.
10. Запись о багаже пассажира авиарейса содержит следующие поля: номер рейса, дата и время вылета, пункт назначения, фамилия пассажира, количество мест багажа, суммарный вес багажа. Поиск выполнять по номеру рейса, дате вылета, пункту назначения, весу
багажа (превышение максимально допустимого).
11. Одна учетная запись посещения спорткомплекса имеет структуру: фамилия клиента, код и вид спортивного занятия, фамилия тренера, дата и время начала, количество минут, тариф за минуту. Поиск по фамилии клиента и тренера, по виду занятия, по дате начала, по количеству минут (больше или меньше).
12. Одна запись о медикаменте содержит следующие поля: номер аптеки, название
лекарства, количество упаковок, имеющееся в наличии в данной аптеке, стоимость одной
упаковки, дата поступления в аптеку, срок хранения (в днях). Поиск по номеру аптеки,
наименованию препарата, дате поступления.
13. Одна запись журнала содержит поля: код игрушки, название игрушки, тип игрушки, возрастные границы (например, от 10 до 15), цена за единицу, количество в наличии,
дата поступления в магазин, поставщик. Поиск по дате поступления, поставщику, возрастным границам.
14. Один элемент — автомобиль — представляет собой в базе данных структуру с
полями: фамилия владельца, код марки автомобиля, марка автомобиля, требуемая марка
бензина, мощность двигателя, объем бака, остаток бензина, объем масла. Дана фиксированная цена литра бензина и заливки масла. Поиск по марке автомобиля, марке бензина, мощности двигателя, фамилии владельца.
15. Одна запись в журнале зимней экзаменационной сессии представляет собой
структуру с полями: курс, код группы, фамилия студента, номер зачетной книжки, дисциплина, оценка за экзамен по дисциплине. Вычисляются средние баллы тю дисциплине, по
группе, по курсу. Поиск по курсу, по группе, по номеру зачетной книжки, по фамилии, по
оценкам.
16. Структура одной записи оплаты за коммунальные услуги содержит поля: номер
дома, номер квартиры, фамилия владельца, вид платежа (квартплата, газ, вода, электричество), дата платежа, сумма платежа, процент пени, на сколько дней просрочен платеж. Поиск по номеру дома, квартиры, владельцу, виду платежа, по дате.
17. Одна запись счета за ремонтные работы содержит поля: название фирмы, вид работ, единица измерения, стоимость единицы выполненных работ, дата исполнения, количество выполненной работы. Поиск по названию фирмы, виду работ, по дате исполнения.
30
18. Одна учетная запись журнала стоянки автомобилей имеет структуру: номер автомобиля, фамилия владельца, дата и время начала, дата и время окончания, тариф за час. Поиск по номеру автомобиля, по дате/времени стоянки, по фамилии владельца.
19. Структура одной записи о сельскохозяйственном продукте содержит поля:
наименование района (где выращивают), наименование продукта, площадь (га), урожайность (кг/га), цена за 1 кг, потери при транспортировке (%), стоимость продукта. Поиск по
наименованию района, по наименованию продукта, по урожайности, по площади.
20. В туристической фирме учетная запись о проданном туре содержит следующие
поля: наименование тура, фамилия клиента, цена 1 дня (в р.), количество дней, стоимость
проезда, курс валюты, количество валюты, стоимость поездки. Поиск выполнять по наименованию тура, по фамилии клиента, по стоимости проезда, по количеству
Download