Cyfroteka.pl

klikaj i czytaj online

Cyfro
Czytomierz
00250 006125 13651830 na godz. na dobę w sumie
ASP.NET 3.5. Programowanie - książka
ASP.NET 3.5. Programowanie - książka
Autor: , , Liczba stron: 1088
Wydawca: Helion Język publikacji: polski
ISBN: 978-83-246-2212-2 Data wydania:
Lektor:
Kategoria: ebooki >> komputery i informatyka >> programowanie >> .net - programowanie
Porównaj ceny (książka, ebook, audiobook).

Kompletne źródło informacji na temat ASP.NET!

Aplikacje internetowe cieszą się wciąż rosnącą popularnością. Na rynku narzędzi do ich tworzenia można znaleźć wiele rozwiązań, a wśród nich jedno wyjątkowe - platformę .NET. Pozwala ona na wykorzystanie dowolnego obsługiwanego przez nią języka programowania do tworzenia dynamicznych, interaktywnych i atrakcyjnych rozwiązań internetowych. Wybierając platformę .NET, otrzymasz dostęp do wielu dodatkowych narzędzi i - co najważniejsze - do wiedzy zgromadzonej przez całą używającą jej społeczność. Niezliczona liczba stron, artykułów i osób chętnych do pomocy sprawia, że rozwiązanie nawet najbardziej skomplikowanego problemu staje się łatwiejsze.

Dzięki tej książce zdobędziesz wiedzę pozwalającą Ci na swobodne poruszanie się w świecie aplikacji internetowych opartych o .NET. Nauczysz się w maksymalny sposób wykorzystywać możliwości środowiska Visual Studio 2008, poznasz dostępne kontrolki oraz sprawdzisz, do czego może Ci się przydać ADO.NET. Ponadto odkryjesz tajemnice języka LINQ i zasady, których przestrzeganie zapewni bezpieczeństwo Twojej aplikacji. W kolejnych rozdziałach autorzy przedstawią Ci metody tworzenia usług sieciowych, zwiększania wydajności poprzez buforowanie oraz konfiguracji serwera IIS 7.0. Książka ta pozwoli Ci w łatwy sposób wykonać pierwszy krok w świat dynamicznych stron WWW, tworzonych z wykorzystaniem ASP.NET.

Poznaj możliwości jednej z najpopularniejszych platform do tworzenia dynamicznych stron WWW!

Znajdź podobne książki Ostatnio czytane w tej kategorii

Darmowy fragment publikacji:

ASP.NET 3.5. Programowanie Autorzy: Jesse Liberty, Dan Maharry, Dan Hurwitz T³umaczenie: Robert Górczyñski ISBN: 978-83-246-2212-2 Tytu³ orygina³u: Programming ASP.NET 3.5 Format: 168×237, stron: 1088 Kompletne Ÿród³o informacji na temat ASP.NET! (cid:129) Jak maksymalnie wykorzystaæ mo¿liwoœci Visual Studio? (cid:129) Jakie tajemnice kryje jêzyk LINQ? (cid:129) Jak tworzyæ bezpieczne aplikacje internetowe? Aplikacje internetowe ciesz¹ siê wci¹¿ rosn¹c¹ popularnoœci¹. Na rynku narzêdzi do ich tworzenia mo¿na znaleŸæ wiele rozwi¹zañ, a wœród nich jedno wyj¹tkowe – platformê .NET. Pozwala ona na wykorzystanie dowolnego obs³ugiwanego przez ni¹ jêzyka programowania do tworzenia dynamicznych, interaktywnych i atrakcyjnych rozwi¹zañ internetowych. Wybieraj¹c platformê .NET, otrzymasz dostêp do wielu dodatkowych narzêdzi i – co najwa¿niejsze – do wiedzy zgromadzonej przez ca³¹ u¿ywaj¹c¹ jej spo³ecznoœæ. Niezliczona liczba stron, artyku³ów i osób chêtnych do pomocy sprawia, ¿e rozwi¹zanie nawet najbardziej skomplikowanego problemu staje siê ³atwiejsze. Dziêki tej ksi¹¿ce zdobêdziesz wiedzê pozwalaj¹c¹ Ci na swobodne poruszanie siê w œwiecie aplikacji internetowych opartych o .NET. Nauczysz siê w maksymalny sposób wykorzystywaæ mo¿liwoœci œrodowiska Visual Studio 2008, poznasz dostêpne kontrolki oraz sprawdzisz, do czego mo¿e Ci siê przydaæ ADO.NET. Ponadto odkryjesz tajemnice jêzyka LINQ i zasady, których przestrzeganie zapewni bezpieczeñstwo Twojej aplikacji. W kolejnych rozdzia³ach autorzy przedstawi¹ Ci metody tworzenia us³ug sieciowych, zwiêkszania wydajnoœci poprzez buforowanie oraz konfiguracji serwera IIS 7.0. Ksi¹¿ka ta pozwoli Ci w ³atwy sposób wykonaæ pierwszy krok w œwiat dynamicznych stron WWW, tworzonych z wykorzystaniem ASP.NET. (cid:129) Praca w zintegrowanym œrodowisku programistycznym Visual Studio 2008 (cid:129) Podstawowe kontrolki oraz kontrolki pozwalaj¹ce na dostêp do danych (cid:129) Dostêp do baz danych z wykorzystaniem ADO.NET (cid:129) Zastosowanie jêzyka LINQ (cid:129) Gwarancja poprawnoœci danych (cid:129) Zapewnienie bezpieczeñstwa aplikacji internetowej (cid:129) Tworzenie stron wzorcowych (cid:129) Przygotowanie us³ug sieciowych (cid:129) Protoko³y i standardy us³ug sieciowych (cid:129) Poprawa wydajnoœci poprzez zastosowanie buforowania (cid:129) Konfiguracja serwera IIS 7.0 (cid:129) Debugowanie kodu i œledzenie jego wykonania (cid:129) Wdra¿anie aplikacji w œrodowisku lokalnym i globalnym (cid:129) Przydatne skróty klawiaturowe Poznaj mo¿liwoœci jednej z najpopularniejszych platform do tworzenia dynamicznych stron WWW! Spis treļci Wstýp ........................................................................................................................................9 1. Programowanie sieciowe .............................................................................................17 17 18 21 22 22 24 Technologia Ajax Platforma .NET 3.0 i 3.5 Visual Studio 2008 Internet Information Services 7.0 WyjĈcie poza VS2008 Oprogramowanie VS2008 2. Visual Studio 2008 .......................................................................................................25 27 28 35 40 Pierwsze spojrzenie: strona poczñtkowa Utworzenie pierwszej strony internetowej Projekty i rozwiñzania Zintegrowane Ĉrodowisko programistyczne 3. Kontrolki — podstawowe zaĥoŜenia .......................................................................... 81 84 92 107 111 116 Zdarzenia Kontrolki serwerowe ASP.NET Kontrolki serwerowe AJAX Kontrolki serwerowe HTML Przetwarzanie po stronie klienta 4. Kontrolki podstawowe ...............................................................................................121 122 127 128 129 139 142 UĔywanie Visual Studio nie jest obowiñzkowe Formularze sieciowe: zwykäe czy AJAX? Kontrolki Label i Literal Kontrolka TextBox Kontrolka HiddenField Kontrolki Button 3 Kontrolka HyperLink Elementy graficzne Zaznaczanie wartoĈci 148 150 159 5. Kontrolki zaawansowane .........................................................................................205 205 230 238 247 261 267 272 Kontrolka Panel Kontrolka UpdatePanel Kontrolki MultiView i View Kontrolka Wizard Kontrolka FileUpload Kontrolka AdRotator Kontrolka Calendar 6. Podstawy witryny internetowej ...............................................................................295 295 298 301 315 334 337 Klasa Page Plik ukrytego kodu PrzejĈcie na innñ stronö Stan Cykl Ĕyciowy Dyrektywy 7. Kontrolki Śródeĥ danych oraz poĥéczenia .................................................................343 343 345 350 353 379 đródäa danych i kontrolki Ēródeä danych UĔywanie kontrolki ObjectDataSource UĔywanie kontrolki XmlDataSource UĔywanie kontrolki SqlDataSource ćledzenie uaktualnieþ za pomocñ zdarzeþ 8. UŜywanie kontrolek dostýpu do danych ..................................................................383 384 385 386 392 412 425 Hierarchiczne kontrolki danych Kontrolki danych tabelarycznych Listy danych Jeden rekord w danej chwili: kontrolka DetailsView Wiele rekordów jednoczeĈnie: kontrolka GridView Kontrolki bazujñce na szablonach 9. ADO.NET ..................................................................................................................... 451 451 457 468 477 484 Model obiektowy ADO.NET Rozpoczynamy pracö z ADO.NET Röczne tworzenie obiektów danych Procedury skäadowane Uaktualnianie za pomocñ SQL i ADO.NET 4 _ Spis treļci Uaktualnianie danych za pomocñ transakcji ãñczenie z obiektami Business 489 502 10. Prezentacja LINQ .......................................................................................................507 508 528 529 537 Budowa LINQ Dostawcy LINQ LINQ to XML LINQ to SQL 11. Sprawdzanie poprawnoļci ........................................................................................555 558 562 566 572 574 576 579 Kontrolka RequiredFieldValidator Kontrolka Summary Kontrolka CompareValidator Sprawdzanie zakresu WyraĔenia regularne Kontrolka CustomValidator Sprawdzanie poprawnoĈci grup 12. Bezpieczeħstwo na bazie formularzy ......................................................................583 585 599 Uwierzytelnianie Szczegóäowy opis uwierzytelniania na bazie formularzy 13. Strony wzorcowe i nawigacja ...................................................................................633 633 646 665 Strony wzorcowe Nawigacja Filtrowanie na podstawie systemu bezpieczeþstwa 14. Personalizacja ............................................................................................................ 671 671 692 700 Tworzenie spersonalizowanych witryn internetowych Tematy i skórki Web Parts 15. Kontrolki wĥasne oraz kontrolki uŜytkownika ..........................................................713 714 728 741 743 Kontrolki uĔytkownika Kontrolki wäasne Tworzenie kontrolek pochodnych Tworzenie kontrolek zäoĔonych 16. Usĥugi sieciowe ..........................................................................................................753 754 755 758 762 Wprowadzenie do usäug sieciowych Zrozumienie protokoäów i standardów usäugi sieciowej UĔywanie usäug sieciowych SOAP Tworzenie usäugi sieciowej ASP.NET SOAP Spis treļci _ 5 Wywoäywanie usäugi sieciowej Tworzenie usäugi sieciowej WCF Tworzenie i uĔywanie usäug sieciowych w technologii Ajax Wprowadzenie do REST i JSON Wiöcej informacji na temat usäug sieciowych 771 776 787 793 804 17. Buforowanie i wydajnoļë ..........................................................................................807 808 809 815 822 827 843 845 851 Rodzaje buforowania Buforowanie danych Buforowanie danych wyjĈciowych Buforowanie czöĈciowe: buforowanie fragmentu strony Buforowanie obiektów Klasa HttpCachePolicy WydajnoĈè Testowanie wydajnoĈci i profilowanie 18. Logika aplikacji i konfiguracja ...................................................................................853 853 860 884 894 920 925 Wprowadzenie do IIS 7.0 Logika o zasiögu caäej aplikacji Konfiguracja aplikacji Modyfikacja pliku web.config za pomocñ IIS 7.0 Web Site Administration Tool Wäasne sekcje konfiguracyjne 19. Ļledzenie, usuwanie i obsĥuga bĥýdów .................................................................... 931 931 934 941 957 959 Tworzenie przykäadowej aplikacji ćledzenie Wykrywanie i usuwanie bäödów Obsäuga bäödów Wäasne strony bäödów 20. WdroŜenie ..................................................................................................................963 964 976 982 984 998 Podzespoäy WdroĔenie lokalne WdroĔenie globalne Instalator Windows Web Deployment Projects 21. Epilog: od teraŚniejszoļci do vNext ........................................................................ 1005 1005 1008 1013 (Niektóre) wyselekcjonowane procesy Projekty w realizacji Na horyzoncie 6 _ Spis treļci A Instalacja pakietu AJAX Control Toolkit ..................................................................1015 1015 1016 1017 Pobranie pakietu Zbudowanie kodu Integracja z pakietem VS2008 B Wprowadzenie do technologii relacyjnych baz danych ........................................ 1023 1023 1024 1026 1029 Tabele, rekordy i kolumny Projekt tabeli SQL Zasoby dodatkowe C Skróty klawiaturowe ................................................................................................1031 1031 1032 1033 1034 1036 1038 1039 1040 1040 Ogólne dziaäania Generowanie tekstu i refaktoring Nawigacja po tekĈcie Edycja tekstu i zaznaczeþ Skróty klawiaturowe w oknie gäównym Skróty klawiaturowe okna Tool Skróty klawiaturowe okna Find and Replace Skróty klawiaturowe dotyczñce makr Skróty klawiaturowe podczas usuwania bäödów Skorowidz ........................................................................................................................... 1043 Spis treļci _ 7 ROZDZIAĤ 10. Prezentacja LINQ Jednym z gäównych dodatków do wydania 3.5 platformy .NET jest LINQ (Language Integrated Query), czyli nowy interfejs programowania aplikacji (API), bödñcy w zasadzie zbiorem prze- strzeni nazw oraz klas säuĔñcych jednemu celowi: pobieraniu danych z dowolnych Ēródeä. Czytelnik moĔe siö zastanawiaè, dlaczego firma Microsoft zdecydowaäa siö na dostarczenie kolejnego sposobu pracy z obiektami Ēródeä danych, skoro technologia ADO.NET doskonale sprawdza siö na tym polu. Czy wprowadzenie LINQ nie jest bezcelowe? OtóĔ nie. W roz- dziale 7. pokazano, jak obiekty .NET DataSource zapewniajñ moĔliwoĈè wspóäpracy z danymi pochodzñcymi z róĔnych Ēródeä — obiektów Business, pliku XML lub bazy danych. Ponadto w rozdziale 9. pokazano, Ĕe technologia ADO.NET oferuje znacznie dokäadniejszñ kontrolö nad dostöpem do bazy danych. Cofnijmy siö jednak o krok i zastanówmy nad sposobem codzien- nej pracy z danymi: x Bardzo rzadko zdarza siö tak, Ĕe wszystkie wymagane dane znajdujñ siö w tym samym Ēródle. Niektóre mogñ znajdowaè siö w bazie danych, kolejne w obiektach Business, a jeszcze inne w punkcie koþcowym usäugi sieciowej itd. x ãatwoĈè, z jakñ moĔna uzyskaè dostöp do danych, jest caäkowicie uzaleĔniona od miejsca ich przechowywania. Uzyskanie dostöpu do obiektów umieszczonych w pamiöci okazuje siö znacznie äatwiejsze niĔ uzyskanie dostöpu do danych przechowywanych w pliku XML bñdĒ bazie danych. x Same nieprzetworzone dane bardzo czösto nie stanowiñ produktu koþcowego. Po ich zebraniu potrzeba sortowania, modyfikacji, grupowania, zmiany kolejnoĈci, zapötlenia, poäñczenia w pojedynczñ pulö itd. Warto zatem spojrzeè na poniĔszy fragment kodu: List Book books = GetBooks(); // Sortowanie. books.SortByPrice(delegate(Book first, Book second)) { return ((double)(second.Price - first.Price)); } // Zapötlenie oraz agregacja. double totalIncome = 0; books.ForEach(delegate(Book book)) { totalIncome += (book.Price * book.TotalSales); } 507 x PowyĔej w szeĈciu krótkich wierszach kodu przeprowadzono sortowanie, zapötlenie i agre- gacjö. Przyjöto jednak zaäoĔenie, Ĕe cena nie jest pobierana poprzez odczyt oddzielnych Ēródeä, takich jak arkusz kalkulacyjny, usäuga sieciowa lub plik XML. Powstaje wiöc pytanie, dlaczego nie skorzystaè z lepszego API säuĔñcego do pobierania danych. Takie API mogäoby oferowaè äatwy dostöp do wszystkich Ēródeä danych, a takĔe moĔliwoĈè äñczenia danych pochodzñcych z wielu Ēródeä. Nastöpnie na poäñczonych danych moĔna przeprowadzaè standardowe operacje, to wszystko w pojedynczym wierszu kodu. Przykäadowo, pojedyncza operacja sprawdzaäaby, czy wszystkie pola danych sñ ĈciĈle okreĈlone, wiöc odpada koniecznoĈè rzutowania obiektu na wäaĈciwy rodzaj podczas pobierania obiektu z bazy danych. Inny przykäad to uäatwienie programistom tworzenia dostawców dostöpu do danych, które nie sñ jeszcze obsäugiwane. Takie moĔliwoĈci daje LINQ, którego kod jest podobny do poniĔszego: var query = from book in Books where book.QuarterlySales 0 select book = {Name, (Price * QuarterlySales) as QuarterlyIncome} orderby QuarterlySales; LINQ uĔywa wielu nowych funkcji C# 3.0 w celu przedstawienia skäadni znanej z SQL, którñ moĔna zastosowaè na dowolnej liczbie odmiennych Ēródeä danych w celu wykonywania zapy- taþ i przetwarzania otrzymanych danych. LINQ to API o naprawdö potöĔnych moĔliwoĈciach. W rozdziale zostanie omówione dziaäanie LINQ, znajdzie siö tu takĔe wyjaĈnienie, dlaczego dziaäa tak dobrze. Bödzie mowa równieĔ o sposobach integracji LINQ z tworzonymi stronami ASP.NET. W szczególnoĈci przyjrzymy siö uĔywaniu LINQ z bazñ danych SQL Server oraz obsäugñ wbudowanñ w Visual Studio 2008 (VS2008), dziöki której stosowanie nowego API jest niemal banalne. Zapoznamy siö takĔe z LinqDataSource, czyli nowñ kontrolkö DataSource stosujñcñ w swoich poleceniach wyraĔenia LINQ. LINQ to obszerny temat, na tyle duĔy, Ĕe moĔna by poĈwiöciè mu oddzielnñ ksiñĔkö, podobnie jak technologiom uĔywajñcym LINQ. Dokäadniejsze omówienie LINQ moĔna znaleĒè w ksiñĔkach LINQ in Action (autor Fabrice Marguerie i inni, wydawnictwo Manning) oraz Pro LINQ (autor Joseph C. Rattz, Jr., wydawnictwo Apress). Warto takĔe zapoznaè siö z ponad piöciuset przykäadowymi fragmentami kodu umieszczonymi na stronie MSDN Code Gallery pod adresem http://code.msdn.microsoft.com/csharpsamples. Budowa LINQ PrzejdĒmy od razu do kodu i zobaczmy bardzo proste wyraĔenie LINQ w dziaäaniu. Po urucho- mieniu VS2008 naleĔy utworzyè nowñ witrynö internetowñ o nazwie C10_LINQ przeznaczonñ dla wszystkich przykäadów omówionych w rozdziale. Pracö rozpoczynamy od utworzenia i uruchomienia kilku zapytaþ wzglödem znajdujñcej siö w pamiöci listy ksiñĔek. Dziöki temu poznamy podstawowñ skäadniö zapytaþ oferowanñ przez LINQ. W VS2008 trzeba kliknñè menu Website/Add New Item, a nastöpnie wskazaè Class jako rodzaj pliku dodawanego do witryny internetowej. Nowej klasie naleĔy nadaè nazwö Book.cs, ustawiè jözyk jako C# i kliknñè przycisk OK. W pliku klasy trzeba umieĈciè kod przedstawiony na lis- tingu 10.1. 508 _ Rozdziaĥ 10. Prezentacja LINQ Listing 10.1. Peäny kod pliku klasy Books.cs using System; using System.Collections.Generic; public class Book { public string ISBN { get; set; } public string Title { get; set; } public decimal Price { get; set; } public DateTime ReleaseDate { get; set; } public static List Book GetBookList() { List Book list = new List Book (); list.Add(new Book { ISBN = 0596529562 , ReleaseDate = Convert.ToDateTime( 2008-07-15 ), Price = 30.0m, Title = Programming ASP.NET 3.5 }); list.Add(new Book { ISBN = 059652756X , ReleaseDate = Convert.ToDateTime( 2008-06-15 ), Price = 26.0m, Title = Programming .NET 3.5 }); list.Add(new Book { ISBN = 0596518455 , ReleaseDate = Convert.ToDateTime( 2008-07-15 ), Price = 28.0m, Title = Learning ASP.NET 3.5 }); list.Add(new Book { ISBN = 0596518439 , ReleaseDate = Convert.ToDateTime( 2008-03-15 ), Price = 25.0m, Title = Programming Visual Basic 2008 }); list.Add(new Book { ISBN = 0596527438 , ReleaseDate = Convert.ToDateTime( 2008-01-15 ), Price = 31.0m, Title = Programming C# 3.0 }); return list; } } Jak moĔna zauwaĔyè, klasa Book zawiera cztery wäaĈciwoĈci oraz jednñ metodö statycznñ, która zwraca listö piöciu ksiñĔek kaĔdej stronie potrzebujñcej choè jednej. Klasa pokazuje równieĔ jednñ z nowych funkcji jözyka w C# 3.0 — inicjalizatory obiektu — za pomocñ której moĔna konstruowaè egzemplarz obiektu bez koniecznoĈci uĔywania wczeĈniej zdefiniowa- nego konstruktora. Wiöcej informacji na temat inicjalizatorów obiektu oraz innych nowych funkcji C# 3.0 Czytelnik znajdzie na kolejnych stronach rozdziaäu. Teraz do witryny dodajemy nowñ stronö internetowñ o nazwie SimpleQuery.aspx, a na stronie umieszczamy kontrolkö Label nazwanñ lblBooks. Po przejĈciu do pliku ukrytego kodu naleĔy dodaè kod przedstawiony na listingu 10.2. Listing 10.2. Plik ukrytego kodu SimpleQuery.aspx.cs using System; using System.Collections.Generic; using System.Linq; using System.Web.UI; public partial class SimpleQuery : Page { protected void Page_Load(object sender, EventArgs e) { List Book books = Book.GetBookList(); // UĔywanie doäñczania wewnötrznego. var bookTitles = Budowa LINQ _ 509 from b in books select b.Title; foreach (var title in bookTitles) { lblBooks.Text += String.Format( {0} br / , title); } } } Po zapisaniu i uruchomieniu strony moĔna siö przekonaè, Ĕe kontrolka Label po prostu wyĈwietla tytuäy ksiñĔek z listy, tak jak pokazano na rysunku 10.1. Rysunek 10.1. Strona SimpleQuery.aspx w dziaäaniu MoĔna zadawaè sobie pytanie, w jaki sposób to wszystko dziaäa. Dowolne zapytanie LINQ moĔna wykonaè wzglödem dowolnej klasy danych dziedziczñcej po IEnumerable T , na przykäad List Book uĔytej w powyĔszym przykäadzie. Aby zagwarantowaè, Ĕe zapytanie bödzie mogäo byè wykonane wzglödem starszych zbiorów .NET v1.x, list itd., przestrzeþ nazw System.Linq zawierajñca implementacjö dla wszystkich operatorów zapytania (select, from itd.) ma takĔe metodö OfType T . Wymienionñ metodö moĔna zastosowaè w dowolnej klasie dziedziczñcej po IEnumerable w celu jej konwersji na jednñ z dziedziczñcych po IEnumerable T (jeĔeli programista nie chce przeprowadzaè rzutowania klasy), która takĔe bödzie mogäa zostaè uĔyta wraz z LINQ. JeĔeli Czytelnik zastanawia siö co oznacza przyrostek T w nazwie klasy, wyja- Ĉniamy, Ĕe to jest sposób deklarowania Generics, czyli funkcji jözyka wprowadzonej w C# 2.0. W jözyku C# 1.0 moĔna byäo zadeklarowaè obiekt List, ale jego treĈè zawsze byäa traktowana jako podstawowe obiekty C#, a nie jako obiekt Book lub Customer. Ogólne rodzaje, metody i interfejsy wprowadzone w C# 2.0 pozwalajñ na zastñpienie znaku T w ich deklaracji dowolnñ nazwñ rodzaju, która bödzie zachowywana pod- czas operacji ogólnych — stñd List Book lub OfType Customer . Wiöcej informacji na temat Generics moĔna znaleĒè w ksiñĔce Programming C# 3.0, autorstwa Jessiego Liberty’ego i Donalda Xie (wydawnictwo O’Reilly). Rzeczywiste zapytanie LINQ jest bardzo proste i moĔe byè zinterpretowane bardziej jak pole- cenie SQL, chociaĔ z klauzulami w nieco odmiennej kolejnoĈci: var bookTitles = from b in books select b.Title; 510 _ Rozdziaĥ 10. Prezentacja LINQ Zapytania LINQ mogñ byè umieszczane w pojedynczym wierszu, ale znacznie bardziej czytelne bödzie rozbicie ich na kilka wierszy, podobnie zresztñ jak w przypadku SQL. Nie naleĔy jednak zapominaè, Ĕe podobieþstwo miödzy LINQ i SQL dotyczy jedynie säów kluczowych, ale juĔ nie samego przetwarzania. Jest to odzwierciedlone przez kolejnoĈè klauzul w zapytaniu. Zapytanie przechodzi przez listö ksiñĔek (Books) i zwraca zbiór implementujñcy IEnumera ´ble T , gdzie T oznacza rodzaj obiektu wynikowego. KaĔdy element zbioru jest tytuäem ksiñĔki w postaci ciñgu tekstowego, tak wiöc bookTitles jest typu IEnumerable String (obiekt StringCollection). PoniewaĔ jednak moĔna uĔyè nowej funkcji C# 3.0, czyli typu anonimowego, to nie trzeba podawaè typu przed wykonaniem zapytania. W takim przypadku kompilator samodzielnie okreĈli odpowiedni typ. Uff! WczeĈniejsze zapytanie moĔna zapisaè takĔe w poniĔszej postaci: var bookTitles = books.Select(b = b.Title); ChociaĔ jest nieco trudniejsze w odczycie, pokazuje drugñ nowñ funkcjö C# 3.0 stosowanñ przez to proste zapytanie. WyraĔenia Lambda oznaczone operatorem = pobierajñ obiekt lub zestaw obiektów i zwracajñ (projekt) niektórych wäaĈciwoĈci metodzie Select (lub innemu ope- ratorowi zapytania) do uĔycia w innym miejscu. WyraĔenia Lambda zostanñ szczegóäowo omó- wione w dalszej czöĈci rozdziaäu. Wiedzñc, Ĕe zapytania LINQ zwracajñ zbiór pewnego rodzaju, oraz znajñc zawartoĈè tego zbioru, ostatni wiersz kodu przechodzi przez wynik zapytania i umieszcza tytuäy wszystkich ksiñĔek we wäaĈciwoĈci Text kontrolki Label: foreach (var title in bookTitles) { lblBooks.Text += String.Format( {0} br / , title); } Ponownie w pötli foreach moĔna wykorzystaè typowanie anonimowe, aby uproĈciè sobie pracö z wynikami zapytaþ LINQ. Säowo kluczowe var nadal jest ĈciĈle okreĈlone — po prostu sugerowane przez kompilator — i nie okreĈla rodzaju jak säowo kluczowe var znane uĔyt- kownikom Visual Basic. Powstaje pytanie, czy moĔna ustawiè dla wäaĈciwoĈci DataSource jednej z kontrolek Ēródeä danych przedstawionych w rozdziale 8. wynik zapytania LINQ. Dowiedzmy siö tego. Do witryny internetowej naleĔy dodaè nowñ stronö o nazwie SimpleQuery2.aspx, a na stronie trzeba umie- Ĉciè kontrolkö GridView nazwanñ gvwBooks. Po przejĈciu do pliku ukrytego kodu naleĔy umieĈciè w nim procedurö obsäugi zdarzeþ Page_Load i polecenia using z listingu 10.2. Jedyna zmiana, którñ trzeba wprowadziè, to usuniöcie pötli foreach i zastñpienie jej poniĔszym przy- pisaniem bookTitles do wäaĈciwoĈci DataSource kontrolki GridView: gvwBooks.DataSource = bookTitles; gvwBooks.DataBind(); Po uruchomieniu strony widzimy, Ĕe kontrolka GridView zostaäa wypeäniona tytuäami ksiñĔek, tak jak pokazano na rysunku 10.2. Warto przy tym zwróciè uwagö, Ĕe nagäówek kolumny jest opisany jako „Item”. NaleĔy ponownie spojrzeè na wyraĔenie LINQ uĔywane do pobrania tytuäów ksiñĔek z listy: var bookTitles = from b in books select b.Title; Budowa LINQ _ 511 Rysunek 10.2. Wynik zapytania LINQ uĔyty jako Ēródäo danych dla kontrolki GridView W przeciwieþstwie do polecenia SQL takiego jak: SELECT title FROM Books wyniki polecenia LINQ sñ zbiorem anonimowych wartoĈci, dlatego kontrolka GridView nadaäa kolumnie nazwö Item. Kontrolka wie, Ĕe w zbiorze wynikowym znajdujñ siö wartoĈci, ale nie wie, jakie sñ nazwy wäaĈciwoĈci lub pól, gdyĔ nie zostaäy nazwane. Nie bödzie to duĔym problemem w przypadku kontrolki GridView, ale po zastñpieniu kontrolki GridView kontrolkñ uĔywajñcñ szablonów, na przykäad ListView, problem stanie siö istotny. Zmieþmy wiöc kontrolkö GridView na kontrolkö uĔywajñcñ szablonów. W kodzie strony SimpleQuery2.aspx usuwamy kontrolkö GridView i dodajemy ListView, jak przedstawiono na listingu 10.3. Listing 10.3. Kod Ēródäowy strony SimpleQuery2.aspx wraz z kontrolkñ ListView @ Page Language= C# AutoEventWireup= true CodeFile= SimpleQuery2.aspx.cs Inherits= SimpleQuery !DOCTYPE html PUBLIC -//W3C//DTD XHTML 1.0 Transitional//EN http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd html xmlns= http://www.w3.org/1999/xhtml head runat= server title Proste zapytanie Linq /title /head body form id= form1 runat= server div asp:ListView runat= server ID= lvwBooks LayoutTemplate ul asp:PlaceHolder runat= server ID= itemPlaceholder / /ul /LayoutTemplate ItemTemplate li # Eval( Title ) /li /ItemTemplate /asp:ListView /div /form /body /html 512 _ Rozdziaĥ 10. Prezentacja LINQ Najwiökszy problem stanowi nazwa pola doäñczana do wiersza przedstawionego pogrubionñ czcionkñ. Wybierane jest pole b.Title, wiöc prawdopodobnie moĔna je nazwaè „Title”. Jednak po zapisaniu i uruchomieniu kodu zobaczymy komunikat bäödu, co pokazano na rysunku 10.3. Rysunek 10.3. Problemy z doäñczaniem wartoĈci anonimowych pobranych przez LINQ Rozwiñzaniem jest nadanie kaĔdej pobieranej wartoĈci nazwy, której nastöpnie moĔna uĔyè pod- czas operacji doäñczania. Kod przedstawiony na listingu 10.4 pokazuje rozwiñzanie omówionego problemu. Listing 10.4. Nadawanie nazw wybranym wäaĈciwoĈciom using System; using System.Collections.Generic; using System.Linq; using System.Web.UI; public partial class SimpleQuery : Page { protected void Page_Load(object sender, EventArgs e) { List Book books = Book.GetBookList(); // UĔywanie wäaĈciwoĈci DataSource. var bookTitles = from b in books select new { Title = b.Title }; lvwBooks.DataSource = bookTitles; this.DataBind(); } } Budowa LINQ _ 513 Podobnie jak na wczeĈniejszym listingu 10.1, wäaĈciwoĈciom zbioru wynikowego bookTitles moĔna nadaè nazwy, które kontrolkom uĔywajñcym szablonów pozwolñ na prawidäowe doäñ- czenie danych. Po zapisaniu i ponownym uruchomieniu strony zauwaĔymy, Ĕe kontrolka ListView zgodnie z oczekiwaniami doäñczyäa wyniki zapytania. W omówionym przykäadzie zapytanie tworzy nowy typ anonimowy z pojedynczñ wäaĈciwo- Ĉciñ o nazwie Title dla kaĔdej ksiñĔki wymienionej na liĈcie. Nastöpnie rzutuje tytuä ksiñĔki do wäaĈciwoĈci Title nowego typu. select new {Title = b.Title} PoniewaĔ typ jest anonimowy, taka operacja nosi nazwö rzutowania anonimowego. Nowy nazwany typ moĔna utworzyè takĔe „w locie”, jeĈli zachodzi taka potrzeba: select new CatalogItem {Title = b.Title} W powyĔszym przykäadzie zapytanie wykonuje rzutowanie nieanonimowe. Skĥadnia LINQ Jak dotñd w zapytaniach LINQ widzieliĈmy jedynie operatory from i select. W rzeczywistoĈci dostöpnych jest znacznie wiöcej operatorów, które implementujñ wszystkie najczöĈciej stoso- wane klauzule w zapytaniu (zobacz tabela 10.1). Tabela 10.1. NajczöĈciej stosowane klauzule zapytania LINQ wymienione w kolejnoĈci ich wykonywania Sĥowo kluczowe from join, on let where orderby, orderbydescending select group Opis Definiuje zakres (zestaw) poczétkowy danych, do których nastýpuje zapytanie. Definiuje dodatkowy zestaw danych, które mogé byë wciégniýte do zapytania. Ponadto definiuje ich powiézanie z pierwszym zestawem danych opisanym w klauzuli from. Definiuje zmienné uŜywané w grupowaniu bédŚ filtrowaniu. Filtruje zestaw danych za pomocé pewnego warunku Boolean. Definiuje kolejnoļë sortowania wyników zapytania. Definiuje wartoļci zwracane z elementów znajdujécych siý w zakresie danych (bardzo czýsto jako wĥaļciwoļci anonimowo okreļlonych obiektów). Okreļla, w jaki sposób zakres danych powinien byë grupowany wokóĥ zmiennej zdefiniowanej przez klauzulý let lub jednej z wĥaļciwoļci w danych. Operatorom wymienionym w tabeli przyjrzymy siö po kolei, a nastöpnie ogólnie zapoznamy siö z peänym zestawem operatorów implementowanych przez LINQ. Klauzula from Pierwszñ klauzulñ w zapytaniu LINQ zawsze jest from: from book in Books Definiuje ona gäówne Ēródäo danych w zapytaniu, które musi implementowaè IEnumerable T . JeĔeli typ zmiennej Books uĔytej w powyĔszym fragmencie kodu implementuje jedynie IEnume ´rable, to moĔna uĔyè metody LINQ OfType T w celu konwersji typu: from book in Books.OfType Book () 514 _ Rozdziaĥ 10. Prezentacja LINQ Na listingu 10.5 przedstawiono uĔycie metody OfType T w ten sposób do przeprowadzenia konwersji tablicy obiektów BookStats — których za chwilö uĔyjemy podczas demonstracji klauzuli join — na typ dziedziczñcy po IEnumerable BookStat . Do katalogu App_Code witryny naleĔy dodaè nowy plik klasy o nazwie BookStats.cs, a nastöpnie umieĈciè w nim kod przedstawiony na listingu 10.5. Listing 10.5. Plik BookStts.cs z uĔyciem OfType T using System.Collections.Generic; using System.Linq; public class BookStats { public int Sales { get; set; } public int Pages { get; set; } public int Rank { get; set; } public string ISBN { get; set; } public static IEnumerable BookStats GetBookStats() { BookStats[] stats = { new BookStats { ISBN = 0596529562 , Pages=904, Rank=1, Sales=109000}, new BookStats { ISBN = 0596527438 , Pages=607, Rank=2, Sales=58000}, new BookStats { ISBN = 059652756X , Pages=704, Rank=3, Sales=75000}, new BookStats { ISBN = 0596518455 , Pages=552, Rank=4, Sales=120000}, new BookStats { ISBN = 0596518439 , Pages=752, Rank=5, Sales=37500} }; return stats.OfType BookStats (); } } Klauzula join JeĔeli w zapytaniu majñ byè wykorzystane dodatkowe Ēródäa danych, naleĔy uĔyè klauzuli join oraz säowa kluczowego on w celu zdefiniowania sposobu powiñzania dodatkowych danych z juĔ wymienionymi w zapytaniu. Przykäadowo, aby poäñczyè przedstawione na lis- tingu 10.5 obiekty BookStats z listñ ksiñĔek przedstawionñ na listingu 10.1, moĔna uĔyè poniĔ- szego kodu: IEnumerable Book books = Book.GetBookList(); IEnumerable BookStats stats = BookStats.GetBookStats(); var bookTitles = from b in books join s in stats on b.ISBN equals s.ISBN select new { Name = b.Title, Pages = s.Pages }; W omawianym przykäadzie kod spowoduje poäñczenie dwóch zbiorów danych, bazujñc jedy- nie na wspóädzielonych przez nie informacjach — czyli numerze ISBN ksiñĔki. Wynik zapy- tania bödzie wiöc zawieraä zarówno dane ksiñĔek, jak i zbiór danych statystycznych. W zasadzie dziaäa to dokäadnie tak samo jak polecenie SQL INNER JOIN. Podobnie jak w SQL, klauzula join moĔe byè uĔyta wielokrotnie do poäñczenia wszystkich wymaganych oddzielnych Ēródeä danych w pojedynczym zapytaniu. Budowa LINQ _ 515 Zapytanie w dziaäaniu zostaäo pokazane na stronie SimpleJoin.aspx, która znajduje siö w materiaäach doäñczonych do ksiñĔki. Klauzula let Klauzula let pozwala na zdefiniowanie wartoĈci przeznaczonej do uĔycia w kolejnych czöĈciach zapytania. Klauzulö moĔna wiöc stosowaè w taki sam sposób jak zmiennñ lokalnñ w metodzie. O ile zmienna ma zasiög w trakcie wykonywania metody, o tyle zasiög klauzuli let ma däugoĈè jednej iteracji w Ēródle danych podczas wykonywania zapytania. ZaäóĔmy na przykäad, Ĕe trzeba obliczyè zysk netto ze sprzedaĔy ksiñĔek w zbiorze. W tym celu moĔna uĔyè poniĔszego zapytania: IEnumerable Book books = Book.GetBookList(); IEnumerable BookStats stats = BookStats.GetBookStats(); var bookTitles = from b in books join s in stats on b.ISBN equals s.ISBN let profit = (b.Price * s.Sales) select new { Name = b.Title, GrossProfit = profit }; JeĔeli wartoĈci te zostanñ doäñczone do kontrolki ListView lub innej kontrolki danych, zysk netto bödzie prawidäowo obliczony i wyĈwietlony po kolei dla kaĔdej ksiñĔki, jak pokazano na rysunku 10.4. Rysunek 10.4. Klauzula let w dziaäaniu Warto pamiötaè, Ĕe w zapytaniu moĔna umieĈciè dowolnñ liczbö klauzul let. Zapytanie w dziaäaniu zostaäo pokazane na stronie SimpleLet.aspx, która znajduje siö w materiaäach doäñczonych do ksiñĔki. Klauzula where Klauzula where pozwala na stosowanie filtrów warunkowych na zbiorze danych, wzglödem którego jest wykonywane zapytanie. JeĔeli filtr przyjmie wartoĈè true dla obiektu aktualnie przetwarzanego w zbiorze, obiekt ten bödzie doäñczony do zbioru wynikowego. JeĈli filtr przyj- mie wartoĈè false, bieĔñcy obiekt nie zostanie umieszczony w zbiorze wynikowym. 516 _ Rozdziaĥ 10. Prezentacja LINQ Przykäadowo, celem zapytania moĔe byè pobranie listy ksiñĔek, których sprzedaĔ przekro- czyäa 60 000 sztuk (to musi byè szczöĈliwy dzieþ!). Tego rodzaju zapytanie moĔna zbudowaè nastöpujñco: IEnumerable Book books = Book.GetBookList(); IEnumerable BookStats stats = BookStats.GetBookStats(); var bookTitles = from b in books join s in stats on b.ISBN equals s.ISBN where s.Sales 60000 select new { Name = b.Title, Sales = s.Sales}; Istnieje równieĔ moĔliwoĈè jednoczesnego zastosowania wielu filtrów. Przykäadowo, jeĔeli zachodzi potrzeba pobrania listy ksiñĔek, które nie zostaäy jeszcze wydane i majñ ponad 700 stron, w zapytaniu moĔna umieĈciè dwie klauzule where: var bookTitles = from b in books join s in stats on b.ISBN equals s.ISBN where b.ReleaseDate DateTime.Now where s.Pages 700 select new {Name = b.Title, ReleaseDate = b.ReleaseDate, Pages = s.Pages}; Dopóki klauzula where zwraca wartoĈè Boolean, dopóty moĔna zastosowaè jñ wewnñtrz innej klauzuli where. Zapytanie w dziaäaniu zostaäo pokazane na stronie SimpleWhere.aspx, która znajduje siö w materiaäach doäñczonych do ksiñĔki. Klauzule orderby i orderbydescending Klauzule orderby i orderbydescending pozwalajñ na sortowanie wyniku zapytania w kolej- noĈci wskazanej na podstawie wartoĈci jednej lub wiökszej liczby wäaĈciwoĈci w zbiorze wy- nikowym. Przykäadowo, przedstawione poniĔej zapytanie zwróci listö wszystkich ksiñĔek posortowanñ w kolejnoĈci wydania od najstarszej do najnowszej. JeĔeli wiöcej niĔ jedna ksiñĔka bödzie miaäa takñ samñ datö wydania, to zostanñ posortowane wzglödem liczby stron: IEnumerable Book books = Book.GetBookList(); IEnumerable BookStats stats = BookStats.GetBookStats(); var bookTitles = from b in books join s in stats on b.ISBN equals s.ISBN orderby b.ReleaseDate, s.Pages select new {Name = b.Title, Pages = s.Pages, ReleaseDate = b.ReleaseDate}; UĔycie klauzuli orderbydescending zamiast orderby powoduje odwrócenie kolejnoĈci sor- towania. Zapytanie w dziaäaniu zostaäo pokazane na stronie SimpleOrderBy.aspx, która znajduje siö w materiaäach doäñczonych do ksiñĔki. Budowa LINQ _ 517 Klauzula select Ostatniñ czöĈciñ zapytania LINQ zawsze musi byè klauzula select — albo sama klauzula, albo jako czöĈè klauzuli groupby, która zostanie omówiona jako kolejna. Wymienione klauzule definiujñ informacje pobierane przez zapytanie. Jak juĔ wczeĈniej pokazano, klauzulö select moĔna wykorzystaè w nastöpujñcych celach: x pobrania pojedynczego fragmentu informacji typu anonimowego lub nazwanego; x rzutowania wielu fragmentów informacji na typ anonimowy bñdĒ nazwany; x pobrania caäego obiektu, wzglödem którego jest wykonywane zapytanie. Ponadto wäaĈciwoĈci wymienionych typów anonimowych lub nazwanych bödñ miaäy nadane nazwy, choè muszñ byè wyraĒnie zarejestrowane, gdy dane bödñ doäñczane do kontrolek ser- werowych ASP.NET. JeĔeli nazwa nie zostanie wyraĒnie ustawiona, zastosowana bödzie taka sama nazwa, jakñ ma wäaĈciwoĈè wskazywana w pierwszej kolejnoĈci. Przykäadowo, poniĔsze zapytanie zwraca zbiór egzemplarzy typów anonimowych zawierajñcych wäaĈciwoĈè o nazwie Title: var bookTitles = from b in books select b.Title; Z kolei poniĔsze zapytanie zwraca zbiór obiektów CategoryItem, z których kaĔdy ma dwie wäaĈciwoĈci o nazwach Title oraz BookId: var bookTitles = from b in books select new CategoryItem { b.Title, BookId = b.ISBN }; Wreszcie kolejne zapytanie zwraca zbiór obiektów przechowywanych w bookTitles. Obiekty te zachowajñ wäasne nazwy oraz wäaĈciwoĈci, jeĔeli nie bödñ typami anonimowymi: var bookTitles = from b in books where b.ReleaseDate DateTime.Now select b; Klauzuli select moĔna uĔyè takĔe do przeksztaäcenia wyników na postaè uäatwiajñcñ pracö: var bookTitles = from b in books select new { ISBN = b.ISBN, ISBN13 = 978- + b.ISBN }; var bookTitles = from b in books select new { ISBN = b.ISBN, Released = (b.ReleaseDate DateTime.Now ? NiedostĀpna : Juş wkrótce )}; Zapytanie w dziaäaniu zostaäo pokazane na stronie SimpleSelect.aspx, która znajduje siö w materiaäach doäñczonych do ksiñĔki. Klauzula group Klauzula group definiuje sposób, w jaki wyniki zapytania powinny byè zwracane w postaci grup, oraz wäaĈciwoĈè kluczowñ, na której ma bazowaè grupowanie. Przykäadowo, jeĔeli zachodzi potrzeba pobrania listy ksiñĔek pogrupowanych na podstawie tego, czy zostaäy juĔ wydane, moĔna uĔyè poniĔszego zapytania: 518 _ Rozdziaĥ 10. Prezentacja LINQ var bookTitles = from b in books join s in stats on b.ISBN equals s.ISBN let outYet = (b.ReleaseDate DateTime.Now ? NiedostĂpna : Juš wkrótce ) orderby s.Rank group new { Title = b.Title, Price = b.Price, Pages = s.Pages } by outYet into groupedBooks select new { Status = groupedBooks.Key, Values = groupedBooks }; Jak moĔna zauwaĔyè, grupowanie powoduje zwiökszenie poziomu skomplikowania zapyta- nia, ale warto zastanowiè siö na otrzymanymi wynikami. Zamiast pojedynczego zbioru wyni- kowego (IEnumerable Results ) zapytanie podzieli zbiór na kilka oddzielnych na podsta- wie wartoĈci kluczowej. Dlatego teĔ zapytanie obecnie zwraca kolekcjö (zbiór wyników oraz wartoĈè wäaĈciwoĈci, wzglödem której wyniki zostaäy pogrupowane). W rzeczywistoĈci, po umieszczeniu kursora myszy nad bookTitles w przedstawionym kodzie, lista IntelliSense pokazuje prawdziwñ strukturö wyników (zobacz rysunek 10.5). Rysunek 10.5. Prawdziwa struktura pogrupowanych danych Wracamy do zapytania. Klauzula group przedstawiona pogrubionñ czcionkñ w powyĔszym fragmencie kodu skäada siö z dwóch oddzielnych czöĈci. W wierszu pierwszym zdefiniowano rzeczywiste informacje, które powinny byè pobrane dla kaĔdej ksiñĔki (wystarczy po prostu zastñpiè säowo kluczowe group säowem select, aby poznaè sens tego wiersza): group new { Title = b.Title, Price = b.Price, Pages = s.Pages } Pozostaäa czöĈè definiuje sposób, w jaki rzeczywiste informacje bödñ podzielone na grupy. Zdefiniowano zmiennñ lokalnñ o nazwie outYet, która moĔe przyjñè jednñ z dwóch wartoĈci. Informacje o ksiñĔce zostanñ wiöc podzielone na dwie grupy w zaleĔnoĈci od wartoĈci zmiennej outYet dla kaĔdej ksiñĔki: by outYet KaĔda grupa (do której lokalnie siö odnosimy, uĔywajñc nazwy znajdujñcej siö po säowie klu- czowym into) bödzie przechowywaäa wartoĈè outYet w swojej wartoĈci Key: into groupedBooks W celu zakoþczenia zapytania pogrupowane dane sñ zbierane za pomocñ wartoĈci klucza, wzglödem której zostaäy pogrupowane: select new { Status = groupedBooks.Key, Values = groupedBooks }; Budowa LINQ _ 519 Nowa struktura wyników zapytania oznacza, Ĕe nie moĔna ich teraz po prostu uĔyè jako Ēródäa danych dla prostej kontrolki doäñczajñcej dane, takiej jak ListView. Zamiast tego trzeba röcznie przejĈè przez kolekcjö i pobieraè pogrupowane dane oraz wartoĈci kluczowe, a nastöp- nie przejĈè ponownie przez pogrupowane dane w celu pobrania zwracanych przez nie infor- macji. Aby zademonstrowaè takie rozwiñzanie, do witryny C10_LINQ dodajemy nowñ stronö internetowñ o nazwie SimpleGroupBy.aspx. Na stronie umieszczamy pojedynczñ kontrolkö Label o nazwie lblBooks. ZawartoĈè pliku ukrytego kodu zastöpujemy kodem przedstawionym na listingu 10.6. Listing 10.6. Tworzenie i uĔywanie grupowanych zbiorów wynikowych LINQ w pliku SimpleGroupBy.aspx.cs using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Web.UI; public partial class SimpleGroupBy : Page { protected void Page_Load(object sender, EventArgs e) { IEnumerable Book books = Book.GetBookList(); IEnumerable BookStats stats = BookStats.GetBookStats(); var bookTitles = from b in books join s in stats on b.ISBN equals s.ISBN let outYet = (b.ReleaseDate DateTime.Now ? NiedostĂpna : Juš wkrótce ) orderby s.Rank group new { Title = b.Title, Price = b.Price, Pages = s.Pages } by outYet into groupedBooks select new { Status = groupedBooks.Key, Values = groupedBooks }; foreach (var group in bookTitles) { lblBooks.Text += String.Format( h2 {0} /h2 , group.Status); foreach (var book in group.Values) { lblBooks.Text += String.Format( p {0}, {1:c} : {2} stron /p , book.Title, book.Price, book.Pages); } } } } Na rysunku 10.6 pokazano stronö po jej uruchomieniu. Warto jednak zwróciè uwagö, Ĕe chociaĔ nazwy wydajñ siö powiñzane z szablonem grupo- wania kontrolki ListView, to przeznaczenie szablonu nie jest takie samo jak grupowania w zapytaniu LINQ. Nie naleĔy wiöc próbowaè mapowaè ich wzglödem siebie. Inne operatory zapytania LINQ Poza omówionymi powyĔej siedmioma standardowymi klauzulami zapytania LINQ imple- mentuje znacznie wiöcej standardowych operatorów zapytania, które przynajmniej czöĈciowo mogñ byè znane Czytelnikowi. 520 _ Rozdziaĥ 10. Prezentacja LINQ Rysunek 10.6. Strona SimpleGroupBy.aspx w dziaäaniu W celu znacznie dokäadniejszego poznania wszystkich operatorów warto poĈwiöciè chwilö i pobraè przykäady C# dla VS2008 ze strony MSDN Code Gallery pod adresem http://code.msdn.microsoft.com/csharpsamples. Znajduje siö tam okoäo 500 przykäadów zapytaþ LINQ przedstawiajñcych kaĔdy operator znacznie dokäadniej niĔ w niniejszej ksiñĔce. W tabeli 10.2 wymieniono operatory zapytania pobierajñce dwa zbiory danych. WartoĈciñ zwrotnñ jest (w pewien sposób) poäñczenie obu zbiorów. Tabela 10.2. Implementacja ustawiania operatorów arytmetycznych w LINQ Operator Union(set1, set2) Except(set1, set2) Intersect(set1, set2) Concat(set1, set2) Opis UŜywany w celu utworzenia z dwóch zestawów pojedynczego zestawu danych zawierajécego jedynie unikalne elementy obu zestawów. UŜywany w celu utworzenia z dwóch zestawów pojedynczego zestawu danych zawierajécego jedynie wartoļci w set1, które nie znajdujé siý w set2. UŜywany w celu utworzenia z dwóch zestawów pojedynczego zestawu danych zawierajécego jedynie wartoļci w set1, które znajdujé siý takŜe w set2. UŜywany w celu utworzenia z dwóch zestawów pojedynczego zestawu danych, w którym zawartoļë set2 zostanie umieszczona po set1. W tabeli 10.3 wymieniono operatory zapytania generujñce nowy zbiór danych, którego nastöpnie moĔna uĔyè w kodzie. W tabeli 10.4 wymieniono operatory zapytania grupujñce zbiory danych, przeprowadzajñce pewne funkcje na grupie, a nastöpnie zwracajñce pojedynczy zbiór wynikowy. W tabeli 10.5 wymieniono operatory wpäywajñce na liczbö elementów znajdujñcych siö w zbiorze wynikowym zapytania, który zostaje faktycznie zwrócony do kodu. Budowa LINQ _ 521 Tabela 10.3. Implementacja operatorów generowania w LINQ Operator Range(seed, dĪugoŁð) Repeat(wynik, liczba) Empty() Opis Zwraca zestaw wszystkich liczb caĥkowitych z zakresu od seed do (seed+dĪugoŁð-1). Zwraca zestaw zawierajécy dané liczbĂ egzemplarzy wyniku. Zwraca zbiór pusty. Tabela 10.4. Implementacja operatorów matematycznych w LINQ Operator Count() Sum() Min() Max() Average() Aggregate(funkcja) Opis Zwraca liczbý elementów w wywoĥywanym zbiorze. Zwraca sumý elementów (przy zaĥoŜeniu, Ŝe wszystkie sé wartoļciami liczbowymi) w zbiorze. Zwraca najniŜszé wartoļë elementu (przy zaĥoŜeniu, Ŝe wszystkie sé wartoļciami liczbowymi) w zbiorze. Zwraca najwyŜszé wartoļë elementu w zbiorze. Zwraca wartoļë ļrednié w zbiorze liczb. Wykonuje wskazané funkcjý na dwóch pierwszych liczbach zbioru, nastýpnie na obliczonej wartoļci caĥkowitej i trzecim elemencie, dalej na obliczonej wartoļci caĥkowitej i czwartym elemencie itd. Tabela 10.5. Implementacja operatorów ustawiania elementów skäadowych w LINQ Operator Take(in) Skip(int) Reverse() Distinct() First() FirstOrDefault() ElementAt(indeks) Last() LastOrDefault() ElementAtOrDefault(indeks) Single(wyrašenie) SingleOrDefault(wyrašenie) Opis Okreļla liczbý elementów w bazowym zbiorze danych, które býdé zawarte w wyniku zapytania. Okreļla liczbý elementów w bazowym zbiorze danych, które nie býdé zawarte w wyniku zapytania. Odwraca kolejnoļë elementów w zbiorze wynikowym. Upewnia siý, Ŝe zbiór wynikowy nie zawiera duplikatów. Zwraca jedynie pierwszy wynik zapytania. Zwraca jedynie pierwszy wynik zapytania lub wartoļë domyļlné tego rodzaju, jeŜeli zbiór wynikowy zapytania jest pusty. Zwraca jedynie wynik zapytania znajdujécy siý w okreļlonym indeksie zbioru. Zwraca jedynie ostatni wynik zapytania. Zwraca jedynie ostatni wynik zapytania lub wartoļë domyļlné tego rodzaju, jeŜeli zbiór wynikowy zapytania jest pusty. Zwraca jedynie wynik zapytania znajdujécy siý w okreļlonym indeksie zbioru lub wartoļë domyļlné tego rodzaju, jeŜeli zbiór wynikowy zapytania jest pusty. Zwraca pojedynczé wartoļë ze zbioru wynikowego, która powoduje speĥnienie podanego wyraŜenia. JeŜeli nie ma takiej wartoļci lub jest ich wiýcej niŜ jedna, operator zwraca bĥéd. Zwraca pojedynczé wartoļë ze zbioru wynikowego, która powoduje speĥnienie podanego wyraŜenia. JeŜeli jest ich wiýcej niŜ jedna, funkcja zwraca bĥéd. W przypadku braku wartoļci speĥniajécej wyraŜenie zwracana jest wartoļë domyļlna dla danego rodzaju. Wreszcie w tabeli 10.6 wymieniono operatory, które moĔna zastosowaè w klauzuli where zapytania. 522 _ Rozdziaĥ 10. Prezentacja LINQ Tabela 10.6. Implementacja operatorów Boolean w LINQ Operator Any(warunek) All(warunek) SequenceEqual(sekwencjaB) Contains(wartoŁð) Opis Zwraca wartoļë Boolean okreļlajécé, czy podany warunek jest speĥniany przez jakikolwiek element zbioru. Zwraca wartoļë Boolean okreļlajécé, czy podany warunek jest speĥniany przez wszystkie elementy zbioru. Zwraca wartoļë true, jeŜeli sekwencjaB zawiera dokĥadnie te same elementy i w dokĥadnie takiej samej kolejnoļci jak sekwencja, wobec której wywoĥywany jest operator SequenceEqual. Zwraca wartoļë true, jeļli zbiór zawiera podané wartoļë. Za kulisami zapytania LINQ: C# 3.0 w dziaĥaniu Za kulisami zapytanie LINQ moĔe uĔywaè jednoczeĈnie do piöciu nowych funkcji jözyka C# 3.0. Kompilator C# wykorzystuje te funkcje w celu ponownego zapisania zapytania oraz obsäuĔenia wyników zapytania w wymienionych poniĔej wywoäaniach metod i typach deklaracji, których faktycznie moĔe uĔyè: x typy anonimowe i inicjalizatory obiektu; x niejawnie okreĈlone zmienne lokalne; x metody rozszerzajñce; x wyraĔenia Lambda. Przyjrzymy siö kolejno kaĔdej pozycji z powyĔszej listy. Typy anonimowe i inicjalizatory obiektu Bardzo czösto programista nie chce tworzyè nowej klasy wyäñcznie w celu przechowywania wyników zapytania. Jözyki .NET 3.x oferujñ tak zwane typy anonimowe, które pozwalajñ na zadeklarowanie zarówno klasy anonimowej, jak i egzemplarza tej klasy przy uĔyciu inicjaliza- torów obiektu. Przykäadowo, anonimowy obiekt ksiñĔki moĔna zainicjalizowaè w nastöpujñcy sposób: new { Title = Programming ASP.NET 3.5 , ReleaseDate = Convert.ToDateTime( 2008-07-15 ), Stats = bookStats }; PowyĔej przedstawiono deklaracjö klasy anonimowej z trzema wäasnoĈciami — Title, Release ´Data i Stats — oraz inicjalizacjö tych zmiennych za pomocñ ciñgu tekstowego, klasy Date ´Time i egzemplarza klasy BookStats. Kompilator C# moĔe okreĈlaè typy wäaĈciwoĈci na podstawie przypisanych im wartoĈci. Dlatego teĔ wäaĈciwoĈè ReleaseData jest typu DateTime, natomiast wäaĈciwoĈè Stats jest typu BookStats. Podobnie jak w przypadku zwykäych, nazwa- nych klas, klasy anonimowe mogñ mieè wäaĈciwoĈci dowolnego typu. W tle dla kaĔdego nowego typu kompilator C# generuje unikalnñ nazwö. PoniewaĔ do tej nazwy nie moĔna odnieĈè siö w kodzie aplikacji, typ jest uznawany za nieposiadajñcy nazwy. JeĔeli Czytelnik jest ciekaw, to w celu dokäadnego ustalenia wywoäywanych klas moĔe uĔyè aplikacji takiej jak Reflector (http://www.red-gate.com/products/reflector/index.htm). Budowa LINQ _ 523 Niejawnie okreļlone zmienne lokalne W kaĔdym przedstawionym dotñd przykäadzie wyniki zapytania byäy przypisywane zmiennej typu var: var bookTitles = from b in books select b.Title; PoniewaĔ klauzula select zwraca egzemplarz typu anonimowego, nie moĔna jawnie zdefi- niowaè typu IEnumerable T . Na szczöĈcie C# 3.0 oferuje innñ funkcjö, nazywanñ niejawnie okreĈlonymi zmiennymi lokalnymi, które rozwiñzujñ ten problem. Niejawnie okreĈlonñ zmiennñ lokalnñ moĔna zadeklarowaè poprzez ustawienie jej typu jako var: var pages = 902; var isbn = 0596529562 ; var stats = new List BookStats (); var book = new {ISBN = 059652756X , ReleaseDate = Convert.ToDateTime( 2008-06-15 ), Price = 26.0m, Title = Programming .NET 3.5 }; Kompilator C# ustala typ niejawnie okreĈlonej zmiennej lokalnej na podstawie jej wartoĈci poczñtkowej. Dlatego teĔ takñ zmiennñ trzeba zainicjalizowaè podczas jej zadeklarowania. W powyĔszym fragmencie kodu typ pages zostaä ustawiony jako liczba caäkowita, typ isbn jako ciñg tekstowy, a typ stats jako ĈciĈle okreĈlony List T obiektów BookStats. Typ ostatniej zmiennej book jest typem anonimowym zawierajñcym cztery wäaĈciwoĈci: ISBN, ReleaseDate, Price i Title. ChociaĔ w kodzie ten typ nie ma nazwy, kompilator C# po cichu przydziela mu nazwö i Ĉledzi egzemplarze tego typu. W rzeczywistoĈci lista IntelliSense Ĉrodowiska IDE Visual Studio równieĔ jest powiadamiana o typach anonimowych, co pokazano na rysunku 10.7. Rysunek 10.7. Lista IntelliSense Ĉledzi typy anonimowe Jak wyjaĈniono wczeĈniej, wynik dowolnego zapytania LINQ jest zmiennñ typu IEnumerable T , gdzie argument T to typ (anonimowy bñdĒ nazwany), który zawiera nazwane wäaĈciwoĈci w klauzuli select lub group. Po zdefiniowaniu zapytania moĔna przechodziè przez wyniki za pomocñ pötli foreach, jak przedstawiono na wczeĈniejszym listingu 10.2: var bookTitles = from b in books select b.Title; foreach (var title in bookTitles) { lblBooks.Text += String.Format( {0} br / , title); } PoniewaĔ wynik jest niejawnie okreĈlonym IEnumerable T , gdzie T to ciñg tekstowy, zmienna iteracji równieĔ bödzie niejawnie rzutowana do tej samej klasy — String. Dla kaĔ- dego obiektu w zbiorze wynikowym przykäad ten po prostu wyĈwietli wäaĈciwoĈci obiektu. 524 _ Rozdziaĥ 10. Prezentacja LINQ Taka sama zasada ma zastosowanie wzglödem wyników pogrupowanego zapytania przed- stawionego na wczeĈniejszym listingu 10.6: foreach (var group in bookTitles) { lblBooks.Text += String.Format( h2 {0} /h2 , group.Status); foreach (var book in group.Values) { lblBooks.Text += String.Format( p {0}, {1:c} : {2} stron /p , book.Title, book.Price, book.Pages ); } } Zmienna iteracji grupujñca wyniki w pötli zewnötrznej jest typu IEnumerable T , gdzie T oznacza niejawny typ {string, IGrouping string, U }. W tym typie U wskazuje na niejawny typ zmiennej iteracji book — {string, decimal, int}. Metody rozszerzajéce Metody rozszerzajñce to sztuczka stosowana przez kompilator — metody statyczne rozsze- rzajñce klasy, do których w innym przypadku nie moĔna dodawaè metod, na przykäad: someString .PrefixWith( asd ); //Zwraca asdsomeString. zamiast: StringExt.PrefixWith( someString , asd ); JeĔeli Czytelnik zna choè trochö SQL, wyraĔenia zapytania przedstawione w poprzednim podrozdziale okaĔñ siö caäkiem intuicyjne i äatwe do zrozumienia, poniewaĔ LINQ jest for- muäowany w sposób podobny do SQL. PoniewaĔ kod C# jest ostatecznie wykonywany przez .NET CLR, kompilator C# musi przeksztaäciè wyraĔenia zapytania na format zrozumiaäy przez Ĉrodowisko uruchomieniowe platformy .NET. PoniewaĔ CLR rozumie wywoäania metod, które mogñ byè wykonywane, wyraĔenia zapytania LINQ napisane w jözyku C# sñ przeksztaä- cane na seriö wywoäaþ metod. Na przykäad, poniĔsze zapytanie: var query = from book in books where book.Price 25m select book; jest przez kompilator przeksztaäcane na: var query = books.Where(book = book.Price 25m) .Select(book = book); PoniewaĔ metoda select nie wykonuje niczego na ksiñĔce (nie rzutuje obiektu book na innñ postaè), to moĔe zostaè pominiöta: var query = books.Where(book = book.Price 25m); JeĔeli zapytanie zwraca jedynie na przykäad cenö ksiñĔki, polecenie select bödzie miaäo nastö- pujñcñ postaè: var query = books.Where(book = book.Price 25m) .Select(book = book.Price); Budowa LINQ _ 525 W rzeczywistoĈci wszystkie standardowe operatory LINQ sñ metodami rozszerzonymi i pod- czas kompilacji zostanñ przez kompilator napisane na nowo, podobnie jak przedstawiona powyĔej. Tworzenie wĥasnych metod rozszerzajécych Podobnie jak przypadku wszystkich opisanych dotñd funkcji, dla zapewnienia wygody ist- nieje takĔe moĔliwoĈè tworzenia wäasnych metod rozszerzonych w dowolnej aplikacji. JeĔeli programista kiedykolwiek napisaä klasö nazwanñ Utils, StringExt, DateExt itd., to wystö- puje duĔe prawdopodobieþstwo, Ĕe metody znajdujñce siö w wymienionych klasach sñ dobrymi kandydatami do przepisania ich na postaè metod rozszerzajñcych. Zapoznajmy siö z przykäadem. Jednñ z moĔliwych do przepisania metod narzödziowych klasy StringExt jest PrefixWith(). Jak moĔna siö spodziewaè, dodaje ona okreĈlony ciñg tekstowy prefiksu do juĔ istniejñcego. Przed zmianñ jej na metodö rozszerzajñcñ byäa wywoäywana w nastöpujñcy sposób: StringExt.PrefixWith(someString, prefixString); Po zaimplementowaniu jako metoda rozszerzajñca moĔe byè wywoäywana w sposób przed- stawiony poniĔej, prawie jak rzeczywista klasa System.String zawierajñca tö metodö: someString.PrefixWith(prefixString); Zmiana metody „standardowej” na „rozszerzajñcñ” jest bardzo äatwa. Na listingu 10.7 przedsta- wiono peäny kod Ēródäowy klasy, w której PrefixWith zdefiniowano jako metodö rozszerzajñcñ. Listing 10.7. Plik Extensions.cs using System; public static class StringExt { public static string PrefixWith( this string someString, string prefixString) { return prefixString + someString; } } W jözyku C# metoda rozszerzajñca musi byè zdefiniowana jako metoda statyczna klasy sta- tycznej. Pierwszy parametr metody rozszerzajñcej oznaczony säowem kluczowym this zawsze wskazuje typ docelowy, którym w omawianym przykäadzie jest string. Dlatego teĔ powyĔszy kod definiuje PrefixWith jako rozszerzenia klasy string. Wszystkie kolejne parametry sñ zwykäymi parametrami metody rozszerzajñcej. CzöĈè gäówna metody nie róĔni siö niczym od zwykäych metod. Przedstawiona powyĔej funkcja po prostu zwraca przeksztaäcony ciñg tekstowy. Aby uĔyè metody rozszerzajñcej, musi siö ona znajdowaè w tym samym zasiögu, w którym jest kod klienta. JeĔeli metoda rozszerzajñca bödzie zdefiniowana w innej przestrzeni nazw, trzeba zastosowaè dyrektywö using importujñcñ przestrzeþ nazw, w której zdefiniowano metodö rozszerzajñcñ. W przeciwieþstwie do zwykäych metod nie moĔna uĔywaè peänych nazw metod rozszerzajñcej. Poza tym ograniczeniem uĔywanie metody rozszerzajñcej jest identyczne z uĔywaniem dowolnych metod wbudowanych typu docelowego. W omawianym przykäadzie nastöpuje po prostu wywoäanie metody System.String, nawet jeĈli metoda jest elementem skäadowym klasy StringExt. 526 _ Rozdziaĥ 10. Prezentacja LINQ Warto w tym miejscu wspomnieè, Ĕe metody rozszerzajñce sñ w pewnych kwestiach bardziej rygorystyczne od zwykäych metod skäadowych — metody rozszerzajñce mogñ uzyskaè dostöp jedynie do publicznych elementów skäadowych typu docelowego. UniemoĔliwia to naruszenie hermetyzacji typów docelowych. WyraŜenia Lambda WyraĔeþ Lambda moĔna uĔyè w celu zdefiniowania definicji delegatów wewnñtrz kodu. W przedstawionym poniĔej wyraĔeniu: book = book.Price 25m lewy operand — book — jest parametrem danych wejĈciowych. Prawy operand to wyraĔenie Lambda, które sprawdza, czy wäaĈciwoĈè Price obiektu book ma wartoĈè wiökszñ niĔ 25. Nastöpnie rzutuje wartoĈè na postaè typu anonimowego lub nazwanego, który bödzie wynikiem wyraĔenia. Dlatego teĔ dla danego obiektu ksiñĔki przeprowadzane jest sprawdzenie, czy cena ksiñĔki jest wyĔsza niĔ 25. WyraĔenie Lambda nastöpnie zostaje przekazane metodzie Where() w celu przeprowadzenia operacji porównania wzglödem kaĔdej ksiñĔki znajdujñcej siö na liĈcie. Zapytania zdefiniowane z uĔyciem metod rozszerzajñcych sñ nazywane zapytaniami bazujñcymi na metodach. ChociaĔ skäadnia metody i zapytania jest odmienna, to semantycznie sñ iden- tyczne i kompilator przeksztaäca je na taki sam kod IL. Programista moĔe wiöc uĔywaè dowolnej z nich w zaleĔnoĈci od wäasnych upodobaþ. IEnumerable dobrze, IQueryable lepiej Jak juĔ wczeĈniej wspomniano, zapytania LINQ mogñ byè zastosowane jedynie wzglödem typów implementujñcych IEnumerable T . Warto jednak dodaè, Ĕe jeĈli klasa zawiera opra- cowany przez programistö zestaw danych implementujñcych równieĔ IQueryable T (który dziedziczy po IEnumerable T ), takie rozwiñzanie bödzie znacznie bardziej poĔñdane. Przyjmujemy zaäoĔenie, Ĕe mamy obiekt Collection mapujñcy 1000 rekordów w innym kom- puterze, i wykonujemy nastöpujñce zapytanie: for Customer c in Customers where c.Country == uk where c.Age 35 select ...... JeĔeli obiekt Customers implementuje jedynie IEnumerable Customer , zapytanie spowoduje pobranie 1000 rekordów do komputera lokalnego jeszcze przed zastosowaniem jakiegokol- wiek filtrowania. Nastöpnie bödzie stosowaè po kolei kaĔdy filtr (klauzula where), jak pokazano na rysunku 10.8. Rysunek 10.8. Zastosowanie kolejnych filtrów na Ēródle danych IEnumerable T Budowa LINQ _ 527 Zapytanie przechodzi przez kaĔdñ klauzulö znajdujñcñ siö w zapytaniu LINQ, ale jeĈli Ēródäo danych zostaäo zmienione miödzy kolejnymi operacjami, to wyniki bödñ siö róĔniäy. Dla porównania — jeĔeli obiekt Customers implementuje IQueryable Customer , to wszyst- kie operacje filtrowania sñ poäñczone w jednñ (pod wzglödem technicznym oznacza to poäñ- czenie w pojedyncze drzewo wyraĔenia). Dlatego teĔ zapytanie bödzie wykonane w zdalnym komputerze tylko jednorazowo podczas Ĕñdania danych. Technicznie nosi to nazwö wykonania odroczonego, jest szybszym i stabilniejszym sposobem dostarczenia wyników z (ogromnych) Ēródeä danych, jak pokazano na rysunku 10.9. Rysunek 10.9. Wykonanie odroczone, w którym wszystkie filtry zostajñ naäoĔone jednoczeĈnie Poprzez wywoäanie ToList T na samym zapytaniu lub wynikach zapytania istnieje równieĔ moĔliwoĈè wymuszenia wykonania zapytania w dowolnej chwili, na przykäad: List Book books = bookList.Select(book = book.Price 25m).ToList Book (); Dostawcy LINQ A zatem za pomocñ jözyka C# 3.0 LINQ dziaäa w charakterze poĈrednika miödzy C# i dowol- nym magazynem danych. Biblioteki w przestrzeni nazw System.Linq implementujñ róĔne klauzule i operatory zapytania, wymienione w przedstawionych wczeĈniej tabelach od 10.1 do 10.6. Owe operatory z kolei komunikujñ siö z dostawcami LINQ, natomiast LINQ wie, jak zastosowaè te zapytania wzglödem okreĈlonych Ēródeä danych, co pokazano na rysunku 10.10. Platforma .NET 3.5 jest dostarczana z czterema wbudowanymi dostawcami LINQ: x MoĔliwoĈè wykonywania zapytaþ wzglödem tablic, list, säowników i innych znajdujñcych siö w pamiöci Ēródeä informacji zademonstrowana jak dotñd w rozdziale jest znana jako LINQ to Objects i takĔe stanowi czöĈè System.Linq. x MoĔliwoĈè wykonywania zapytaþ wzglödem dokumentu XML jest znana jako LINQ to XML i zostaäa zaimplementowana w System.Xml.Linq. x MoĔliwoĈè wykonywania zapytaþ wzglödem dowolnej bazy danych SQL Server jest znana jako LINQ to SQL i zostaäa zaimplementowana w System.Data.Linq. x MoĔliwoĈè wykonywania zapytaþ do innego, dowolnego rodzaju bazy danych jest obecnie zaimplementowana poprzez umieszczanie danych w obiekcie DataSet znajdujñcym siö w pamiöci, a nastöpnie wykonywanie zapytaþ do wymienionego obiektu. Takñ operacjö umoĔliwia zestaw rozszerzeþ zaimplementowanych w System.Data.DataSetExtensions. Piñty dostawca LINQ znany jako LINQ to Entities jest dostöpny jako czöĈè .NET 3.5 Service Pack 1. To po prostu „przemysäowa” wersja dostawcy LINQ to SQL. 528 _ Rozdziaĥ 10. Prezentacja LINQ Rysunek 10.10. Graficzna prezentacja LINQ i predefiniowanych dostawców Jak pokazano na rysunku 10.10, pewna liczba zewnötrznych dostawców LINQ pozwala na wykonywanie zapytaþ do wielu róĔnych Ēródeä danych, takich jak Oracle, MySQL, Flickr, usäugi sieciowe Amazon, NHibernate i inne. Lista aktualnych zewnötrznych dostawców LINQ znajduje siö na stronie http://oakleafblog. blogspot.com/2007/03/third-party-linq-providers.html, choè wiele z nich jest nazywanych LINQ to xzy. Wyszukiwarka Google prawdopodobnie bödzie najwiökszym przyja- cielem Czytelnika w odkryciu dodatkowych informacji o dostawcy dla Ēródäa, które ma zostaè wykorzystane. Zagadnienie tworzenia wäasnego dostawcy LINQ wykracza poza zakres tematyczny niniejszej ksiñĔki. Istnieje jednak wiele pomocnych zasobów, jeĈli Czytelnik bödzie chciaä spróbowaè. W pozostaäej czöĈci rozdziaäu omówimy dwóch gäównych dostawców dostarczanych z VS2008: LINQ to XML oraz LINQ to SQL. LINQ to XML Dostawca LINQ to XML wczytuje dokument XML do pamiöci i przeksztaäca go na zestaw obiektów (takich jak XElement i XAttribute), wzglödem których moĔna wykonywaè zapytania. Wymienione obiekty w peäni opisujñ dokument i pozwalajñ na poruszanie siö po nich w stylu XPath i XQuery. Na listingu 10.8 przedstawiono bardzo prosty dokument XML zawierajñcy informacje o tym, które ksiñĔki zostaäy napisane przez danego autora. Plik naleĔy utworzyè i dodaè do witryny C10_LINQ. Szczegóäowe informacje dotyczñce autorów znajdujñ siö w bazie danych Adventure- WorksLT, do której dostöp uzyskamy w podrozdziale poĈwiöconemu dostawcy LINQ to SQL. Natomiast informacje szczegóäowe o ksiñĔkach znajdujñ siö w utworzonych wczeĈniej obiektach przechowywanych w pamiöci. LINQ to XML _ 529 Listing 10.8. Plik Authors.xml ?xml version= 1.0 encoding= utf-8 ? authorlist author id= 1 book isbn= 0596529562 / book isbn= 059652756X / /author author id= 10 book isbn= 059652756X / book isbn= 0596527438 / /author author id= 38 book isbn= 0596518439 / /author author id= 201 book isbn= 0596518439 / book isbn= 0596527438 / /author /authorlist Przede wszystkim trzeba utworzyè stronö wyĈwietlajñcñ identyfikatory autorów. Do witryny C10_LINQ dodajemy nowñ stronö internetowñ o nazwie SimpleXmlQuery.aspx. Na stronie umieszczamy kontrolkö Label o nazwie lblAuthors. Plik ukrytego kodu strony zastöpujemy kodem przedstawionym na listingu 10.9. Listing 10.9. Plik ukrytego kodu SimpleXmlQuery.aspx.cs using System; using System.Linq; using System.Web.UI; using System.Xml.Linq; public partial class SimpleXmlQuery : Page { protected void Page_Load(object sender, EventArgs e) { XElement doc = XElement.Load(
Pobierz darmowy fragment (pdf)

Gdzie kupić całą publikację:

ASP.NET 3.5. Programowanie
Autor:
, ,

Opinie na temat publikacji:


Inne popularne pozycje z tej kategorii:


Czytaj również:


Prowadzisz stronę lub blog? Wstaw link do fragmentu tej książki i współpracuj z Cyfroteką: