Âúâåäåíèå â LINQ è îñíîâíè âúçìîæíîñòè
Êàêòî ñïîìåíàõìå ïî-ãîðå çàä àáðåâèàòóðàòà LINQ
ñòîè Language INtegrated
Query. Òîâà å ïðîåêò íà Ìàéêðîñîôò çà äîáàâÿíå ñèíòàêñèñ çà çàÿâêè,
õàðàêòåðåí çà T-SQL, â åçèöèòå îò .NET Framework. Ïúðâîíà÷àëíî òîçè ñèíòàêñèñ ùå ñå ïîääúðæà îò C#
è Visual Basic, íî ñå î÷àêâà äà áúäå âúâåäåí è â
îñòàíàëèòå åçèöè íà ïî-êúñåí åòàï.
LINQ äåôèíèðà ñòàíäàðòíè îïåðàòîðè çà çàÿâêè, êîèòî ïîçâîëÿâàò
íà åçèöèòå ñ ïîääðúæêà íà
LINQ, äà ôèëòðèðàò, èçáðîÿâàò è ñúçäàâàò ïðîåêöèè íà íÿêîëêî
òèïà êîëåêöèè, êàòî èçïîëçâàò åäèíåí ñèíòàêñèñ. Îñíîâíèòå èçòî÷íèöè íà äàííè êúì
ìîìåíòà ñà ìàñèâè, èçáðîèìè êëàñîâå ( èìïëåìåíòèðàùè
èíòåðôåéñèòå ICollection
è IEnumerable ), XML,
DataSet-îâå îò ðåëàöèîííè áàçè äàííè. Êàêòî â ïîâå÷åòî ñè
ïðîäóêòè Ìàéêðîñîôò ñà îñèãóðèëè API (Application Program Interface),
÷ðåç êîéòî òðåòè ñòðàíè ìîãàò äà îñèãóðÿò ïîääðúæêà íà ñâîè èçòî÷íèöè íà äàííè â
LINQ.
Çà äà ñòàíå ïî-ÿñíî êàêâè ñà ïîëçèòå îò LINQ
è ùå íàïðàâèì ïàðàëåë ñúñ SQL çàÿâêèòå.
Ïðåäïîëàãàì ïîâå÷åòî îò âàñ ñà çàïîçíàòè ñúñ çàÿâêèòå â
SQL, íî è äà ãðåøà òîâà íÿìà äà ïîïðå÷è äà ðàçáåðåòå
èçâúðøâàíèòå îïåðàöèè.
Ôèëòðèðàíå â SQL
Íåêà èìàìå òàáëèöà Contact â MS
SQL Server ñúñ ñëåäíèòå êîëîíè è äàííè:
Contact
|
ID
|
ContactName
|
1
|
Galcho
|
2
|
George
|
3
|
Trifon
|
4
|
Kiril
|
5
|
Shumi
|
Çà äà èçâåäåì âñè÷êè çàïèñè çàïèñè îò êîëîíàòà
ContactName, êîèòî çàïî÷âàò çàïî÷âàò ñ áóêâàòà “G”
èçïîëçâàìå ñëåäíàòà çàÿâêà:
SELECT [ContactName]
FROM [Contact]
WHERE [ContactName] LIKE ‘G%’
|
È êàòî ðåçóëòàò ïîëó÷àâàìå:
Äîñòàòú÷íî ïðîñòî, íàëè?
Íî òîâà å êîãàòî èçïúëíÿâàìå çàÿâêèòå íà SQL
ñúðâúð. À êàêâî ñå ïîëó÷àâà, êîãàòî âå÷å ñìå èçâëåêëè äàííèòå îò ñúðâúðà è
èñêàìå ñàìî äà ïðèëîæèì äîïúëíèòåëåí ôèëòúð!? Òîãàâà âàðèàíòèòå ñà:
·
Èçïúëíÿâàìå íîâà çàÿâêà êúì SQL ñúðâúðà
çàåäíî ñ íîâèòå óñëîâèÿ çà ôèëòðèðàíå
·
Ïèøåì äîïúëíèòåëåí êîä çà ôèëòðèðàíå íà ðåçóëòàòèòå.
Óëîâêàòà òóê å, ÷å íå âèíàãè ñå íàëàãà äà ôèëòðèðàìå äàííè,
êîèòî ñà âçåòè îò SQL ñúðâúð. Çàòîâà íåêà ðàçãëåäàìå
ôèëòðèðàíåòî íà ìàñèâè è êîëåêöèè â äîòóê ïîçíàòèòå íè âåðñèè íà C#.
Çà âñåêè ïðèìåð ùå ôèëòðèðàìå òîçè ìàñèâ:
string[] contacts = {
"Galcho",
"George", "Trifon",
"Kiril", "Shumi"
};
|
êàòî ùå èçïîëçâàìå ñúùîòî óñëîâèå – èìåíàòà äà çàïî÷âàò ñ
áóêâàòà ‘G’
Ôèëòðèðàíå â C# 1.1
Çà äà âúðíåì ñúùèÿò ðåçóëòàò å íåîáõîäèìî äà èçïúëíèì ñëåäíèÿò
êîä:
private
void FilterWithCSharp1_1()
{
string[]
contacts = { "Galcho",
"George",
"Trifon",
"Kiril", "Shumi"
};
//display result
foreach
(string
name
in FilterResults(contacts))
{
Console.WriteLine(name);
}
}
private
IEnumerable FilterResults(string[]
Data)
{
//result collection
StringCollection
results = new
StringCollection();
//filter array
foreach
(string
name
in Data)
{
if
(name.StartsWith("G"))
results.Add(name);
}
return
results;
}
|
 òîçè êîä ñëåä
äåôèíèöèÿòà íà âõîäíèòå äàííè èìàìå ñàìî åäíà
foreach êîíñòðóêöèÿ, êîÿòî èçâåæäà ïîñëåäîâàòåëíî
âñåêè åëåìåíò âúðíàò îò ôóíêöèÿòà FilterResults,
íà êîÿòî ïîäàâàìå êàòî ïàðàìåòúð ìàñèâà ñ âõîäíè äàííè.
 íåÿ äåêëàðèðàìå è èíèöèàëèçèðàìå ïðîìåíëèâà
results îò òèï
StringCollection.Ñëåä òîâà ñ ïîìîùòà íà
foreach êîíñòðóêöèÿ, ïðîâåðÿâàìå âñåêè åëåìåíò äàëè
îòãîâàðÿ íà çàäàäåíîòî óñëîâèå ( çàïî÷âà ñ áóêâà “G” ) è
àêî îòãîâàðÿ ãî äîáàâÿìå â êîëåêöèÿòà ñ ðåçóëòàòèòå
results. Íàêðàÿ âðúùàìå
results êàòî ðåçóëòàò.
Ôèëòðèðàíå â C# 2.0
Íåêà äà ðàçãëåäàìå êàê áèõìå ðåàëèçèðàëè òàçè ôóíêöèîíàëíîñò ñúñ
ñðåäñòâàòà, êîèòî ïðåäîñòàâÿ C# 2.0
private
void FilterWithCSharp2()
{
string[]
contacts = { "Galcho",
"George",
"Trifon",
"Kiril", "Shumi"
};
//display result
foreach
(string
name
in FilterResults2(contacts))
{
Console.WriteLine(name);
}
}
private
IEnumerable FilterResults2(string[]
Data)
{
//filter array
foreach
(string
name
in Data)
{
if
(name.StartsWith("G"))
yield return
name;
}
}
|
 òîçè êîä,
ïîäîáíî íà ïðåäèøíèÿò ïðèìåð, èìàìå ñàìî åäíà
foreach êîíñòðóêöèÿ, êîÿòî èçâåæäà ïîñëåäîâàòåëíî âñåêè åëåìåíò âúðíàò îò
ôóíêöèÿòà FilterResults2,
íà êîÿòî ïîäàâàìå êàòî ïàðàìåòúð ìàñèâà ñ âõîäíè äàííè.
Òúíêèÿò ìîìåíò å âúâ ôóíêöèÿòà
FilterResults2. Òàì ñå îñúùåñòâÿâà ôèëòðèðàíåòî íà åëåìåíòèòå è àêî îòãîâàðÿò íà
óñëîâèåòî ñå èçïúëíÿâà îïåðàòîðà yield return, êîéòî âðúùà óïðàâëåíèåòî íà èçâèêâàùàòà ôóíêöèÿ çà âñåêè
çàïèñ ïî îòäåëíî.
Çàáåëåæêà: Ïðåïîðú÷âàì äà
îáõîäèòå äâàòà ïðèìåðà â Debug Mode è ñòúïêà ïî ñòúïêà è
äà îáðúíåòå âíèìàíèå, ÷å âúâ ôóíêöèÿòà
FilterResults ïúðâî ñå îáõîæäàò âñè÷êè åëåìåíòè, à ñëåä
òîâà çàïî÷âà îòïå÷àòâàíåòî íà åêðàí. Êàêòî ïîñî÷èõìå âúâ ôóíêöèÿòà
FilterResults2 íå å òàêà. Òîâà îêàçâà ãîëÿìî âëèÿíèå ïðè îáðàáîòêà íà
ãîëåìè êîëåêöèè, òúé íå å íåîáõîäèìî äà ñå èç÷àêâà îáðàáîòêàòà íà âñè÷êè
åëåìåíòè ïðåäè äà ïðîäúëæè ðàáîòàòà.
Ïîâå÷å çà îïåðàòîðà yield
ìîæå äà ïðî÷åòåòå íà àäðåñ
http://msdn2.microsoft.com/en-us/library/9k7k7cf0.aspx
Êàê ñòàâà òîâà â C# 3.0? Íåêà ðàçãëåäàìå
ñëåäâàùèÿò êîä:
private static
void FilterWithCSharp3() {
string[]
contacts = { "Galcho",
"George",
"Trifon",
"Kiril", "Shumi"
};
var
result = from
s
in contacts
where
s.StartsWith("G")
select
s;
//display result
foreach
(string
name
in result) {
Console.WriteLine(name);
}
}
|
Ñëåä ïúðâîíà÷àëíî íåîáè÷àéíèÿ ñèíòàñèñ èçãëåæäà ìíîãî åëåãàíòíî,
íàëè?! Ìíîãî ïðèëè÷à íà SQL çàÿâêàòà.
Ñúùèÿò ðåçóëòàò ìîæå äà áúäå ïîñòèãíàò è ïî àëòåðíàòèâåí íà÷èí
êàòî èçïîëçâàìå íîâèòå ìåòîäè äåôèíèðàíè â LINQ
àñåìáëèòàòà.
private
static
void
FilterWithCSharp3_2() {
string[]
contacts = { "Galcho",
"George",
"Trifon",
"Kiril", "Shumi"
};
var
result = contacts.Where<string>(x
=> x.StartsWith("G"));
//display result
foreach
(string
name
in result) {
Console.WriteLine(name);
}
}
|
Ïî òîçè íà÷èí ñòàâà äîðè îùå ïî-åëåãàíòíî.
Òîçè ïðèìåð å äîñòàòú÷íî êðàòúê, çà äà ïîêàæå èçìåíåíèÿòà â
ñèíòàêñèñà, îáåìà êîä è ÷èòàåìîñòòà. Ïîêàçàõìå ñàìî èçïîëçâàíåòî ñàìî íà åäèí îò
îïåðàòîðèòå çà çàÿâêè – where.
Íåêà äà íàïðàâèì íåùàòà ìàëêî ïî-ñëîæíè è äà ãðóïèðàìå äàííèòå.
Ãðóïèðàíå ñ LINQ
è C# 3.0
Çà äà ãðóïèðàìå äàííè ùå èìàìå íóæäà îò ïî-ñëîæíè äàííè. Íåêà äà
äåôèíèðàìå êëàñ Employee
ïî ñëåäíèÿò íà÷èí:
public
class
Employee
{
public string
Name;
public string
Department;
public double
Salary;
}
|
Îáúðíåòå âíèìàíèå, ÷å íå äåôèíèðàìå êîíñòðóêòîð è êîìïèëàòîðà
äîáàâÿ êîíñòðóêòîð ïî ïîäðàçáèðàíå (áåç ïàðàìåòðè).
Çàáåëåæêà: Â ðåàëíè ïðîåêòè
å äîáðå äà äåôèíèðàìå ñâîéñòâà, êîèòî äà äîñòúïâàò òåçè ïîëåòà, íî ñ öåë
îïðîñòÿâàíå íà êîäà ñåãà ãè ïðîïóñêàìå.
Äåôèíèðàìå è èíèöèàëèçèðàìå êîëåêöèÿ îò îáåêòè îò òèï
Employee ñúñ ñëåäíèÿò êîä:
Employee[] employees = {
new Employee{Name="Joe", Department="IT",
Salary=1800d},
new Employee{Name="Peter", Department="IT",
Salary=2000d},
new Employee{Name="Jana", Department="Sales",
Salary=900d},
new Employee{Name="Schumacher", Department="Motor
Sport",
Salary=1000000d},
new Employee{Name="Mary", Department="Sales",
Salary=700d},
new Employee{Name="July", Department="Marketing",
Salary=2800d},
};
|
 ñëåäâàùèÿò êîä ùå ãðóïèðàìå ñëóæèòåëèòå ñïîðåä òåõíèÿò îòäåë è
çà äà íàïðàâèì íåùàòà ïî-èíòåðåñíè, ùå ñóìèðàìå çàïëàòèòå íà âñè÷êè ñëóæèòåëè â
îòäåëà. Âå÷å íå å òîëêîâà ëåñíî äà ãî íàïðàâèì ñúñ ñðåäñòâàòà íà C# 2.0,
íàëè?!
var result =
from e
in
employees
group
e by
e.Department
into g
select new
{
Department = g.Key,
Employees = g,
SumSalaries = g.Sum(e => e.Salary)};
//display result
foreach (var dept
in
result) {
//display department name
Console.WriteLine("Department Name:{0} Sum of
Salaries:{1}",
dept.Department, dept.SumSalaries);
//display employees in current department
foreach
(Employee
empl
in dept.Employees) {
Console.CursorLeft
= 4;
Console.WriteLine("Name:{0}, Salary:{1}",
empl.Name, empl.Salary);
}
}
|
 òàçè çàÿâêà ñå èçïúëíÿâàò äâå îñíîâíè ôóíêöèè:
·
Ãðóïèðàíå íà ñëóæèòåëèòå ïî îòäåëè è
·
Ñóìèðàíå íà çàïëàòèòå íà ñëóæèòåëèòå çà âñåêè îòäåë.
Êàòî ðåçóëòàò ñå âðúùà êîëåêöèÿ îò íîâ òèï îáåêòè ñúñ ñâîéñòâà:
·
Department - òåêñòîâ íèç ñ èìåòî íà îòäåëà
·
Employees - êîëåêöèÿ îò îáåêòè òèï ñúñ ñëóæèòåëèòå çà
êîíêðåòíèÿò îòäåë
·
SumSalaries - ÷èñëî ñúäúðæàùî ñóìèòå íà çàïëàòèòå íà
ñëóæèòåëèòå â îòäåëà
Ïîíåæå èìàìå äâå (âëîæåíè) êîëåêöèè, çà äà âèçóàëèçèðàìå
ðåçóëòàòà òðÿáâà äà ðåàëèçèðàìå äâà öèêúëà (ñúùî âëîæåíè). È åòî êàêúâ å èçõîäà
íà åêðàí:
Department Name:IT Sum of Salaries:3800
Name:Joe, Salary:1800
Name:Peter, Salary:2000
Department Name:Sales Sum of Salaries:1600
Name:Jana, Salary:900
Name:Mary, Salary:700
Department Name:Motor Sport Sum of Salaries:1000000
Name:Schumacher, Salary:1000000
Department Name:Marketing Sum of Salaries:2800
Name:July, Salary:2800
|
Ñúâåò: Ïðåìèíåòå ïðåç êîäà
ñòúïêà ïî ñòúïêà êàòî ïðîâåðÿâàòå ñúñòîÿíèåòî íà ïðîìåíëèâèòå. Ïî òîçè íà÷èí ùå
âíèêíåòå â äåòàéëè êàêâî ñòàâà íà âñåêè ðåä îò êîäà.
Ìíîãî å âåðîÿòíî äà ñå ÷óâñòâàòå îáúðêàíè îò òîçè ñèíòàêñèñ. Â
ñëåäâàùèòå ÷àñòè ùå ñå îáÿñíèì íîâèòå åçèêîâè êîíñòðóêöèè è ùå ñå âúðíåì êúì
çàäúëáî÷åíî îáÿñíåíèå íà LINQ ñèíòàêñèñà êàòî ùå ðàçãëåäàìå îùå ïðèìåðè.
Äî ìîìåíòà ðàçãëåäàõìå äâà îò îïåðàòîðèòå çà çàÿâêè -
where è
group by, À èìà îùå
äîñòàòú÷íî ìíîãî (order, join, union, distinct,
except, intersect), ÷èåòî èìïëåìåíòèðàíå â .NET
1.1 è .NET 2.0 íå å òîëêîâà ëåñíî.
Òÿõíîòî èçïîëçâàíå ùå ïîêàæåì ïî-íàòàòúê â òîâà ðúêîâîäñòâî.
Íåêà ñåãà äà ñå âúðíåì ìàëêî íàçàä è äà ðàçãëåäàìå ðàçøèðåíèÿòà â ñèíòàêñèñà íà
C#, êîèòî ïðàâÿò LINQ âúçìîæíî.
Ñëåäâàùà
÷àñò: Èíèöèàëèçèðàíå íà îáåêòè è êîëåêöèè