SlideShare uma empresa Scribd logo
1 de 21
Baixar para ler offline
C# 3.0 i .NET 3.5.
                           Technologia LINQ
                           Autor: Jacek Matulewski
                           ISBN: 83-246-1447-8
                           Format: 158x235, stron: 88



                                                          Poznaj technologiê LINQ
                           aby uzyskaæ swobodny dostêp do danych z SQL Server, pliku XML lub kolekcji
                           z poziomu swoich programów
                               • Bezpieczny dostêp do danych przy zachowaniu kontroli typów
                               • Tworzenie zapytañ LINQ
                               • Budowanie, analiza i pobieranie danych z plików XML
                           Zastosowanie technologii LINQ (ang. Language-Integrated Query, zintegrowany jêzyk
                           zapytañ) w zasadniczy sposób upraszcza projektowanie aplikacji bazodanowych.
                           Zapytanie LINQ zwraca kolekcjê z przestrzeni nazw typów ogólnych. Kolekcja ta mo¿e
                           byæ modyfikowana, a nastêpnie zwrócona do Ÿród³a. Dziêki temu zachowywana jest
                           pe³na kontrola typów danych i ich konwersji w poszczególnych mechanizmach
                           poœrednicz¹cych w pobieraniu danych.
                           Ksi¹¿ka „C# 3.0 i .NET 3.5. Technologia LINQ” prezentuje prosty sposób korzystania
                           ze zintegrowanego jêzyka zapytañ. Dziêki temu podrêcznikowi nauczysz siê pobieraæ
                           dane z ró¿nego rodzaju Ÿróde³; tworzyæ pliki XML w nowy, bardziej intuicyjny sposób;
                           stosowaæ sk³adowane rozszerzenia ? nowego typu metody (oraz odpowiadaj¹ce
                           im operatory), zdefiniowane w najnowszej wersji jêzyka C#. Ponadto dowiesz siê,
                           jak tworzyæ w³asne Ÿród³a danych LINQ. Krótko mówi¹c, z ksi¹¿k¹ „C# 3.0 i .NET 3.5.
                           Technologia LINQ” nawet jako œrednio zaawansowany programista poradzisz sobie
                           ze stworzeniem bardzo skomplikowanych aplikacji bazodanowych.
                               • Wyra¿enia Lambda
                               • Nowe operatory LINQ
                               • Zapytania LINQ
                               • LINQ to DataSet
                               • Aktualizacja danych w bazie
                               • Korzystanie z rozszerzeñ
Wydawnictwo Helion             • Kontrolka LinqDataSource
ul. Koœciuszki 1c              • Tworzenie i modyfikacja pliku XML
44-100 Gliwice                 • Tworzenie Ÿróde³ danych LINQ
tel. 032 230 98 63
                                         Ta ksi¹¿ka wska¿e Ci prosty sposób tworzenia doskona³ych
e-mail: helion@helion.pl
                                                  i nowoczesnych aplikacji bazodanowych
Spis tre ci
                Wstöp .............................................................................................. 5
Rozdziaä 1. Nowo ci jözyka C# 3.0 ..................................................................... 7
                Okre lanie typu zmiennej lokalnej przy inicjalizacji ........................................................ 7
                Wyra enia Lambda ........................................................................................................... 8
                Rozszerzenia ................................................................................................................... 10
                Nowa forma inicjalizacji obiektów i tablic ..................................................................... 12
                Nowe operatory LINQ .................................................................................................... 13
                Typy anonimowe ............................................................................................................ 14
                Przykáad — kolekcja jako ródáo danych ....................................................................... 14
Rozdziaä 2. LINQ i ADO.NET .............................................................................. 21
                Konfiguracja kontrolki DataSet ...................................................................................... 22
                LINQ to DataSet, czyli tam i z powrotem .......................................................................... 24
                Korzy ci z LINQ to DataSet ........................................................................................... 26
Rozdziaä 3. LINQ i SQL Server ........................................................................... 29
                Klasa encji ...................................................................................................................... 29
                Pobieranie danych .......................................................................................................... 31
                Aktualizacja danych w bazie .......................................................................................... 32
                Wizualne projektowanie klasy encji ............................................................................... 35
                Korzystanie z procedur skáadowanych ........................................................................... 44
                Kontrolka LinqDataSource (ASP.NET) ......................................................................... 47
Rozdziaä 4. LINQ i XML .................................................................................... 51
                Tworzenie pliku XML za pomoc klas XDocument i XElement ................................... 51
                Pobieranie warto ci z elementów o znanej pozycji w drzewie ....................................... 54
                Przenoszenie danych z kolekcji do pliku XML .............................................................. 55
                Przenoszenie danych z bazy danych (komponentu DataSet) do pliku XML .................. 56
                Zapytania LINQ .............................................................................................................. 57
                Modyfikacja pliku XML ................................................................................................. 59
Rozdziaä 5. Tworzenie ródeä danych LINQ ......................................................... 61
                IEnumerable ................................................................................................................... 61
                IEnumerable<T> ............................................................................................................ 63
                Oddzielenie ródáa od jego interfejsu ............................................................................. 65
                IQueryable i IOrderedQueryable .................................................................................... 68
4                                                                                  C# 3.0 i .NET 3.5. Technologia LINQ


               IQueryable<T> i IOrderedQueryable<T> ...................................................................... 69
               Drzewo wyra enia .......................................................................................................... 71
               Zadanie. LINQ to TXT ................................................................................................... 78
Dodatek A Wiöcej w sieci… ............................................................................ 83
               Skorowidz ...................................................................................... 85
Rozdziaä 3.
LINQ i SQL Server
   Wspominaj c o technologii LINQ, mówi si zazwyczaj o zanurzeniu j zyka SQL w j -
   zyku C#. W przypadku LINQ to SQL zanurzenie to mo na rozumieü niemal dosáownie
   — zapytanie LINQ jest w tym przypadku táumaczone bezpo rednio na zapytanie SQL
   wysyáane do bazy danych.

   Zacznijmy od prostej sytuacji: poá czmy si z baz danych Telefony.mdf (zob. rysunek 2.3
   z poprzedniego rozdziaáu) i pobierzmy z niej list osób peánoletnich. Wykorzystamy do
   tego obiekt klasy DataContext, która jak na razie wspóápracuje tylko z bazami SQL Server
   (nie dotyczy to jednak lokalnych baz SQL Server Compact Edition). Klasa DataContext
   jest gáówn bram do technologii LINQ to SQL. Brama ta wymaga jednak stra nika. Jego
   rol przejmuje klasa encji, tj. klasa C#, która zdefiniuje typ ka dego rekordu (encji) tabeli
   bazy danych. Dzi ki tej klasie mo liwe jest zbudowanie pomostu mi dzy tabel pobie-
   ran za pomoc zapytania SQL a kolekcj zwracan przez zapytanie LINQ, tj. mi dzy
   typem encji a typem elementu kolekcji. Dzi ki tej klasie w zapytaniu LINQ mo emy
   u ywaü nazw pól, które obecne s w tabeli, wr cz identyfikowaü kolekcj z tabel .

   Zanim przejdziemy do konkretów, chciaábym jeszcze zwróciü uwag Czytelnika na je-
   den istotny fakt. W LINQ to Object, które poznali my w pierwszym rozdziale, ródáem
   danych byáa kolekcja istniej ca w pami ci i w peáni dost pna z poziomu programu. Nie
   byáo zatem konieczno ci odwoáywania do zasobów zewn trznych (np. plików bazy danych).
   Dzi ki temu caáy kod aplikacji mógá byü skompilowany do kodu po redniego. W przy-
   padku LINQ to SQL, którym zajmiemy si w tym rozdziale, lub LINQ to XML, omówio-
   nego w kolejnym rozdziale, taka peána kompilacja nie jest mo liwa. Analiza danych
   pobranych ze ródáa danych mo e odbyü si dopiero w trakcie dziaáania programu.
   Realizowane jest to za pomoc drzewa zapyta , które poznamy dokáadniej w ostatnim
   rozdziale, przy okazji projektowania wáasnego ródáa danych LINQ.



Klasa encji
   Klasa encji (ang. entity class) to zwykáa klasa C#, w której za pomoc atrybutów po-
   wi zane s pola klasy z polami tabeli (kolumnami). Mamy wi c do czynienia z mode-
   lowaniem zawarto ci relacyjnej bazy danych w typowanych klasach j zyka, w którym
30                                                                C# 3.0 i .NET 3.5. Technologia LINQ


           przygotowujemy program. W tym kontek cie u ywany jest angielski termin strongly
           typed, który podkre la izomorficzno ü relacji klasy encji i struktury tabeli. Ów zwi -
           zek jest niezwykle istotny — przede wszystkim umo liwia kontrol typów, która
           w pewnym sensie rozci ga si na poá czenie z baz danych. Dzi ki tej relacji progra-
           mista mo e w pewnym stopniu uto samiaü t klas i reprezentowan przez ni tabel .
           To pozwala równie przygotowywaü zapytania LINQ, korzystaj c z nazw pól tabeli
           — jego táumaczenie na zapytanie SQL jest dzi ki temu szczególnie proste, a jedno-
           cze nie w peáni zachowana jest kontrola typów. Domy lne wi zanie realizowane jest
           na podstawie nazw obu pól. Mo liwa jest jednak zmiana tego domy lnego sposobu
           wi zania oraz zmiana wáasno ci poszczególnych pól.

           Przed caá klas znale ü si powinien atrybut Table z przestrzeni nazw System.Data.
           ´Linq.Mapping, w którym wskazujemy nazw tabeli z bazy danych1. Natomiast przed
           polami odpowiadaj cymi kolumnom w tabeli nale y umie ciü atrybut Column (z tej sa-
           mej przestrzeni nazw), w którym mo emy wskazaü m.in. nazw kolumny w tabeli (pa-
           rametr Name), poinformowaü go, czy jest kluczem gáównym (IsPrimaryKey) lub czy mo e
           przyjmowaü puste warto ci (CanBeNull). Listing 3.1 zawiera przykáad klasy encji,
           w której definiujemy typ rekordu z tabeli ListaOsob z bazy danych Telefony.mdf zna-
           nej z poprzedniego rozdziaáu.2

Listing 3.1. Klasa encji zwi zana z tabel ListaOsob z bazy Telefony.mdf
              [Table(Name = "ListaOsob")]
              public class Osoba
              {
                 [Column(Name = "Id", IsPrimaryKey = true)]
                 public int Id;
                 [Column(Name = "Imiú", CanBeNull = false)]
                 public string Imiú;
                 [Column(Name = "Nazwisko", CanBeNull = false)]
                 public string Nazwisko;
                 [Column]
                 public int NumerTelefonu;
                 [Column]
                 public int Wiek;
              }


           W powy szym listingu wi zanie klasy ze struktur bazy danych przeprowadzane zo-
           staje na podstawie atrybutów doá czanych do definicji klasy. W terminologii Microsoft
           nazywane jest to mapowaniem opartym na atrybutach (ang. attribute-based mapping).

1
    Klasy z przestrzeni nazw System.Data.Linq i jej podprzestrzeni, m.in. z System.Data.Linq.Mapping,
    do której nale y klasa Table, zdefiniowane s w osobnej bibliotece System.Data.Linq.dll, nale cej
    do zbioru bibliotek platformy .NET 3.5. Domy lnie nie jest ona wá czana do zbioru bibliotek projektu.
    Nale y j zatem dodaü samodzielnie, korzystaj c z polecenia Project, Add Reference…. Omówione
    ni ej narz dzie wizualnego projektowania klas encji zwolni nas z tego obowi zku.
2
    Tworz c tabel w bazie SQL Server mogli my zezwoliü, aby niektóre jej pola dopuszczaáy pust warto ü.
    Definiuj c klas encji warto zadeklarowaü odpowiadaj ce im pola klasy w taki sposób, aby dopuszczaáy
    przypisanie warto ci null. W przypadku áa cuchów nie ma problemu – typ String jest typem referencyjnym
    i zawsze mo na mu przypisaü warto ü null. Inaczej wygl da to np. w przypadku typu int, który jest typem
    warto ciowym. Nale y wówczas w deklaracji pola wykorzystaü typ parametryczny Nullable<int>.
Rozdziaä 3. i LINQ i SQL Server                                                                    31


           Mo liwe jest równie podej cie alternatywne, w którym mapowanie odbywa si na
           podstawie struktury zapisanej w pliku XML. Takie podej cie nosi nazw mapowania
           zewn trznego i nie b d si nim tu zajmowaá. Po jego opis warto zajrzeü na stron
           MSDN: http://msdn2.microsoft.com/en-us/library/bb386907.aspx.

              LINQ to SQL daje dobry pretekst do wspomnienia o zagadnieniu modelowania da-
              nych. Jest to ciekawa gaäñ informatyki, ale nie chciaäbym snuè dygresji na jej temat.
              Osoby zainteresowane teoriñ przechowywania danych powinny w Google wpisaè
              hasäo data modeling lub modelowanie danych.


           Jak wspomniaáem wcze niej, klasa encji zwykle nie jest tworzona r cznie. Zwykle do
           jej projektowania wykorzystywany jest edytor O/R Designer, który omówi w dalszej
           cz ci tego rozdziaáu. Wydaje mi si jednak, e przy pierwszych próbach korzystania
           z technologii LINQ to SQL warto zrobiü wszystko samodzielnie. Dotyczy to równie
           powoáywania instancji klasy DataContext, czym zajmiemy si ju za chwil .



Pobieranie danych
           Zacznijmy od zdefiniowania pól przechowuj cych referencje do instancji klasy Data
           ´Context i jej tabeli ListaOsob:
              static string nazwaPliku = "Telefony.mdf";
              static DataContext bazaDanychTelefony =
                 ´new DataContext(System.IO.Path.GetFullPath(nazwaPliku));
              static Table<Osoba> listaOsob = bazaDanychTelefony.GetTable<Osoba>();

           Tworzymy obiekt DataContext i pobieramy z niego referencj do tabeli (klasa Table
           parametryzowana klas encji Osoba). Klasa DataContext znajduje si w przestrzeni
           nazw System.Data.Linq, nale y wi c uwzgl dniü j w grupie polece using3. Ostat-
           nia instrukcja tworzy pole o nazwie listaOsob typu Table parametryzowanego nasz
           klas encji Osoba. Referencja ta b dzie umo liwiaü dost p do danych pobranych z tabeli
           ListaOsob. Nazwa pobieranej tabeli wskazana zostaáa w atrybucie Table, którym poprze-
           dzili my klas encji. Dlatego jej nazwa nie pojawia si w powy szych definicjach.

           Obiekt klasy DataContext reprezentuje baz danych. Z kolei klasa encji zdefiniowana
           w listingu 3.1 dostarcza informacji o strukturze konkretnej tabeli (encji). Dzi ki obu
           klasom mo emy poá czyü si z baz danych i pobraü dane z interesuj cej nas tabeli.
           Prezentuje to listing 3.2.

Listing 3.2. Pobieranie danych z tabeli w bazie SQL Server za pomoc LINQ to SQL
              private void button1_Click(object sender, EventArgs e)
              {
                 //pobieranie kolekcji
                 var listaOsobPelnoletnich = from osoba in listaOsob

3
    Tu stosuje si równie uwaga z poprzedniego przypisu. Ponadto konstruktor klasy DataContext wymaga,
    aby cie ka do pliku podana w argumencie byáa bezwzgl dna (ang. full path).
32                                                     C# 3.0 i .NET 3.5. Technologia LINQ


                                       where osoba.Wiek>=18
                                       select osoba;

           //wy wietlanie pobranej kolekcji
           string s = "Lista osób pe noletnich:n";
           foreach (Osoba osoba in listaOsobPelnoletnich) s+=osoba.Imiú+" "+osoba.Nazwisko
              ´+" ("+osoba.Wiek+")n";
           MessageBox.Show(s);
       }


     W zapytaniu LINQ (pierwsza instrukcja metody widocznej w listingu 3.2) pobiera z ta-
     beli list osób, które maj co najmniej 18 lat. Zwróümy uwag na podobie stwo tego
     zapytania do tego, które stosowali my w przypadku LINQ to Objects w pierwszym roz-
     dziale.

     W listingu 3.2 klasa encji Osoba pojawia si tylko raz w p tli foreach. Co wi cej, skoro
     jest jasne, e ka dy rekord jest obiektem typu Osoba, a to wiadomo dzi ki parametry-
     zacji pola listaOsob, jawne wskazanie typu w tej p tli nie jest konieczne i z równym
     skutkiem mogliby my u yü sáowa kluczowego var — kompilator sam wywnioskowaáby,
     z jakim typem ma do czynienia.



Aktualizacja danych w bazie
     Pobieranie danych, wizytówka LINQ, to zwykle pierwsza czynno ü wykonywana przez
     aplikacje. Technologia LINQ to SQL nie poprzestaje tylko na tym. Zmiany wprowa-
     dzone w pobranej zapytaniem LINQ kolekcji mo na w áatwy sposób przesáaü z powro-
     tem do bazy danych. Sáu y do tego metoda SubmitChanges obiektu DataContext. Tym
     samym wszelkie modyfikacje danych staj si bardzo naturalne: nie ma konieczno ci
     przygotowywania polece SQL, odpowiedzialnych za aktualizacj tabel w bazie da-
     nych — wszystkie operacje wykonujemy na obiektach C#. Zachowana jest w ten spo-
     sób spójno ü programu, co pozwala na kontrol typów i peán weryfikacj kodu ju
     w trakcie kompilacji.

     Modyfikacje istniejñcych rekordów
     Poka my to na prostym przykáadzie. Zaáó my, e mija Nowy Rok i z tej okazji zwi k-
     szamy warto ü w polach Wiek wszystkich osób. Rzecz jasna wszystkich, poza kobie-
     tami, które s ju peánoletnie. Pobieramy zatem kolekcj osób, które s m czyznami
     lub s niepeánoletnie. Spójnik „lub” u yty w poprzednim zdaniu rozumiany powinien
     byü tak, jak zdefiniowany jest operator logiczny OR — powinni my uzyskaü sum mno-
     go ciow zbiorów osób niepeánoletnich i zbioru m czyzn. Nast pnie zwi kszamy war-
     to ü pola Wiek ka dej z osób tak uzyskanego zbioru. I najmilsza rzecz: aby zapisaü nowe
     warto ci do pliku bazy danych, wystarczy tylko wywoáaü metod SubmitChanges na
     rzecz obiektu bazaDanychTelefony. Powy sze czynno ci uj te w j zyku C# prezentuje
     listing 3.3.
Rozdziaä 3. i LINQ i SQL Server                                                                33


Listing 3.3. Modyfikowanie istniej cego rekordu
           private void button2_Click(object sender, EventArgs e)
           {
              //pobieranie kolekcji
              var listaOsobDoZmianyWieku = from osoba in listaOsob
                                           where (osoba.Wiek<18 || !osoba.Imiú.EndsWith("a"))
                                           select osoba;

               //wy wietlanie pobranej kolekcji
               string s = " Lista osób niebúdæcych pe noletnimi kobietami:n";
               foreach (Osoba osoba in listaOsobDoZmianyWieku) s += osoba.Imiú + " " +
                      ´osoba.Nazwisko + " (" + osoba.Wiek + ")n";
               MessageBox.Show(s);

               //modyfikowanie kolekcji
               foreach (Osoba osoba in listaOsobDoZmianyWieku) osoba.Wiek++;

               //wy wietlanie peánej listy osób kolekcji po zmianie
               s = "Lista wszystkich osób:n";
               foreach (Osoba osoba in listaOsob) s += osoba.Imiú + " " + osoba.Nazwisko + " ("
                    ´+ osoba.Wiek + ")n";
               MessageBox.Show(s);

               //zapisywanie zmian
               bazaDanychTelefony.SubmitChanges();
           }


        Musi pojawiü si pytanie, sk d obiekt bazaDanychTelefony (obiekt typu DataContext
        reprezentuj cy w naszej aplikacji baz danych) wie o modyfikacjach wprowadzonych
        do kolekcji listaOsobDoZmianyWieku otrzymanej zapytaniem LINQ z kolekcji uzyskanej
        metod bazaDanychTelefony.GetTable<Osoba>(). Otó st d, e kolekcja listaOsobDo
        ´ZmianyWieku przechowuje tylko referencje do obiektów tej tabeli, a nie kopie tych
        obiektów (por. zapytania LINQ w podrozdziale „Mo liwo ü modyfikacji danych ró-
        dáa”, w rozdziale pierwszym). Zreszt w przypadku LINQ to SQL próba uruchomienia
        zapytania, w którym tworzymy kopie obiektów, sko czy si zgáoszeniem wyj tku
        NotSupportedException. Tak wi c wszystkie zmiany wprowadzane do kolekcji wpro-
        wadzane s automatycznie w buforze obiektu bazaDanychTelefony, przechowuj cym
        dane pobrane z bazy danych. A obiekt ten ju potrafi zapisaü je z powrotem do tabeli
        SQL Server. Warto przy tym pami taü, e wszystkie zmiany wprowadzane w kolekcji
        s przechowywane tylko w niej a do momentu wywoáania metody SubmitChanges. Mo-
         emy wi c dowolnie (wielokrotnie) modyfikowaü kolekcj bez obawy, e nadu ywamy
        zasobów bazy danych i komputera, zmniejszaj c wydajno ü programu.

           W trakcie projektowania aplikacji nale y zwróciè uwagö, czy plik bazy danych widoczny
           w podoknie Solution Explorer jest kopiowany do katalogu, w którym umieszczana jest
           skompilowana aplikacja (podkatalog bin/Debug lub bin/Release). Mo e to wprowadzaè
           pewne zamieszanie i utrudniaè ledzenie zmian w bazie danych np. za pomocñ podokna
           Database Explorer.
34                                                                 C# 3.0 i .NET 3.5. Technologia LINQ


           Dodawanie i usuwanie rekordów
           Co jeszcze mo emy zmieniü w tabeli? W zasadzie pozostaje tylko dodawanie nowych
           i usuwanie istniej cych rekordów. Równie to zadanie jest dzi ki LINQ to SQL bardzo
           proste. W tym przypadku zmiany musz byü jednak wprowadzane wprost w obiekcie
           reprezentuj cym tabel — instancji klasy DataContext, a nie w pobranej z niego ko-
           lekcji. Listing 3.4 pokazuje, jak dodaü do tabeli nowy rekord. Po utworzeniu obiektu
           DataContext (polecenia identyczne jak w poprzednich listingach) obliczamy warto ü
           pola Id dla nowego rekordu — do najwi kszej warto ci Id w tabeli dodajemy jeden4
           — korzystamy przy tym z rozszerzenia Max. Nast pnie tworzymy obiekt typu Osoba
           i poleceniem InsertOnSubmit dodajemy go do tabeli. Rzeczywista zmiana nast pi
           w momencie najbli szego wywoáania metody SubmitChanges obiektu DataContext.

Listing 3.4. Dodawanie rekordu do tabeli
              private void button3_Click(object sender, EventArgs e)
              {
                 //dodawanie osoby do tabeli
                 int noweId = listaOsob.Max(osoba => osoba.Id) + 1;
                 MessageBox.Show("Nowe Id: " + noweId);
                 Osoba noworodek = new Osoba { Id = noweId, Imiú = "Nela", Nazwisko =
                                             ´"Matulewska", NumerTelefonu = 0, Wiek = 0 };
                 listaOsob.InsertOnSubmit(noworodek);

                  //zapisywanie zmian
                  bazaDanychTelefony.SubmitChanges(); //dodawany jest tak e nowy rekord

                  //wy wietlanie tabeli
                  string s = "Lista osób:n";
                  foreach (Osoba osoba in listaOsob) s += osoba.Imiú + " " + osoba.Nazwisko + " ("
                       ´+ osoba.Wiek + ")n";
                  MessageBox.Show(s);
              }


           Równie áatwo usun ü z tabeli rekord lub ich grup . Nale y tylko zdobyü referencj do
           odpowiadaj cego im obiektu (wzgl dnie grupy obiektów). W przypadku pojedyncze-
           go rekordu nale y u yü metody DeleteOnSubmit, w przypadku ich kolekcji — Delete
           ´AllOnSubmit. W obu przypadkach rekordy zostan oznaczone jako przeznaczone do
           usuni cia i rzeczywi cie usuni te z bazy danych przy najbli szym wywoáaniu metody
           SubmitChanges. Listing 3.5 prezentuje metod usuwaj c z tabeli wszystkie osoby
           o imieniu Nela.

Listing 3.5. Wszystkie modyfikacje w bazie danych wykonywane s w momencie wywoáania metody
SubmitChanges
              private void button4_Click(object sender, EventArgs e)
              {
                 //wybieranie elementów do usuni cia i ich oznaczanie
                 IEnumerable<Osoba> doSkasowania = from osoba in listaOsob


4
    Wáa ciwsze byáoby pewnie wyszukanie najmniejszej wolnej warto ci, ale nie chciaáem niepotrzebnie
    komplikowaü kodu. Zreszt zwykle tak post puj , w my l zasady „prosty kod oznacza mniejsze ryzyko bá du”.
Rozdziaä 3. i LINQ i SQL Server                                                                35


                                                 where osoba.Imiú == "Nela"
                                                 select osoba;
               listaOsob.DeleteAllOnSubmit(doSkasowania);

               //zapisywanie zmian
               bazaDanychTelefony.SubmitChanges();

               //wy wietlanie tabeli
               string s = "Lista osób:n";
               foreach (Osoba osoba in listaOsob) s += osoba.Imiú + " " + osoba.Nazwisko + " ("
                    ´+ osoba.Wiek + ")n";
               MessageBox.Show(s);
           }



           Klasa DataContext säu y nie tylko do pobierania i modyfikacji zawarto ci bazy danych.
           Za pomocñ jej metod CreateDatabase i DeleteDatabase mo na tak e tworzyè i usu-
           waè bazy danych SQL Server z poziomu kodu. Za pomocñ metody ExecuteCommand
           mo na wykonaè podane w argumencie polecenie SQL, a za pomocñ ExecuteQuery
           — uruchomiè zapytanie SQL i odczytaè pobrane przez nie dane.




Wizualne projektowanie klasy encji
        W przypadku bardziej rozbudowanych baz danych najpro ciej klas encji utworzyü,
        korzystaj c z wbudowanego w Visual Studio narz dzia, którego nazwa w dosáownym
        táumaczeniu to „projektant obiektowo-relacyjny” (ang. Object Relational Designer,
        w skrócie: O/R Designer) i który w istocie umo liwia automatyczne mapowanie struk-
        tury tabeli bazy danych w klasach C#. Nie chciaáem od niego rozpoczynaü omawiania
        LINQ to SQL, aby daü Czytelnikowi mo liwo ü poznania technologii „od podszewki”,
        tj. od wáasnor cznie przygotowanej klasy encji. Ale skoro ju tak klas sami przy-
        gotowali my, nie musimy tego wi cej powtarzaü. Co prawda samodzielnie przygoto-
        wane klasy encji s zwykle bardziej zwarte, ale pisz c je, mo emy popeániaü bá dy,
        których unikniemy, tworz c klasy myszk .

        O/R Designer
        Zacznijmy od utworzenia klasy encji dla tabeli ListaOsob w bazie Telefony.mdf. W tym
        celu z menu Project wybieramy polecenie Add New Item. Pojawi si okno widoczne
        na rysunku 3.1. Zaznaczamy w nim ikon LINQ to SQL Classes. W polu Name poda-
        jemy nazw nowego pliku: Telefomy.dbml. Po zamkni ciu okna dialogowego zoba-
        czymy now zakáadk . Na razie pust , nie licz c napisów informuj cych, e na dwa
        widoczne na niej panele nale y przenosiü elementy z podokna Database Explorer.

        Przenie my na lewy panel tabel ListaOsob (rysunek 3.2). Konwencja nazw w pliku
        Telefony.dbml nie przystaje niestety do nazw, jakich u yáem w bazie Telefony.mdf. Auto-
        matycznie tworzona klasa encji przejmuje bowiem nazw tabeli, tj. ListaOsob (nasza
        r cznie przygotowana klasa encji nazywaáa si Osoba). Z kolei wáasno ü tylko do od-
        czytu zdefiniowana w klasie TelefonyDataContext, która zwraca tabel (a konkretnie
36                                                    C# 3.0 i .NET 3.5. Technologia LINQ




Rysunek 3.1. Tworzenie klasy reprezentuj cej dane




Rysunek 3.2. Zakáadka z O/R Designer

        kolekcj typu Table<ListaOsob>), nazywa si ListaOsobs z „s” dodanym na ko cu.
        Gdyby tabela nazywaáa si np. Person, klasa encji nazywaáaby si Person, a wáasno ü
        reprezentuj ca tabel — Persons. Wówczas nazwy brzmiaáyby du o lepiej. A tak mamy
        ListaOsobs.
Rozdziaä 3. i LINQ i SQL Server                                                                   37


         Co prawda nazwy utworzonych przez O/R Designera klas mo na áatwo zmieniü — wy-
         starczy na zakáadce Telefony.dbml klikn ü nagáówek tabeli (rysunek 3.2) i wpisaü nowe
         nazwy. To samo dotyczy nazw pól domy lnie ustalonych na identyczne jak znalezione
         w tabeli SQL Server. Je eli wpiszemy nazw ró n od tej w tabeli, O/R Designer zmo-
         dyfikuje atrybut Column, który wska e pole tabeli, z jakim definiowane pole obiektu ma
         byü zwi zane.

         Utworzona przez O/R Designer klasa ListaOsob (mo na j znale ü w pliku Telefony.
         ´designer.cs) jest klas encji o identycznej funkcji jak zdefiniowana przez nas wcze niej
         klasa Osoba. Nie jest jednak z ni identyczna. T pierwsz O/R Designer wyposa yá poza
         polami, które i my zdefiniowali my, równie w zbiór metod i zdarze . Zawiaduje nimi
         O/R Designer i poza wyj tkowymi sytuacjami raczej nie nale y edytowaü ich kodu.
         Same pola, inaczej ni w naszej prostej implementacji, s w nowej klasie prywatne
         i poprzedzone znakiem podkre lenia. Zwróümy uwag , e te z nich, które odpowiadaj
         tym polom tabeli, które dopuszczaj pust warto ü, zdefiniowane zostaáy przy u yciu
         typu parametrycznego System.Nullable<typ>, gdzie typ to oryginalny typ danych .NET
         (w naszym przypadku int lub string). Dost p do tych pól mo liwy jest poprzez pu-
         bliczne wáasno ci. Przykáad takiej wáasno ci odpowiadaj cej polu Id widoczny jest na
         listingu 3.6. Wáasno ü poprzedzona jest atrybutem Column, którego u ywali my te
         w naszej wcze niejszej klasie encji. Jej argumenty s jednak inne (poza IsPrimaryKey
         ustawionym na true). Ze wzgl du na identyczn nazw pola tabeli i wáasno ci klasy
         argument Name zostaá tu pomini ty. Dwa nowe argumenty to Storage, który wskazuje
         prywatne pole przechowuj ce warto ü komórki, oraz DbType. W tym ostatnim przecho-
         wywana jest informacja o oryginalnym typie pola tabeli (kolumny). Tworzy go nazwa
         typu dozwolona przez SQL Server (np. Int lub NVarChar(MAX)), uzupeániona ewentu-
         alnie fraz NOT NULL, je eli baza nie dopuszcza pustych warto ci dla tego pola.

Listing 3.6. Wáasno ü Id klasy ListaOsob. Towarzyszy jej pole zdefiniowane jako private int _Id

            [Column(Storage="_Id", DbType="Int NOT NULL", IsPrimaryKey=true)]
            public int Id
            {
               get
               {
                   return this._Id;
               }
               set
               {
                   if ((this._Id != value))
                   {
                      this.OnIdChanging(value);
                      this.SendPropertyChanging();
                      this._Id = value;
                      this.SendPropertyChanged("Id");
                      this.OnIdChanged();

                }
            }
38                                                            C# 3.0 i .NET 3.5. Technologia LINQ


         Wspomniana klasa reprezentuj ca caá baz danych zawiera wáasno ci odpowiadaj ce
         tabelom bazy. Jest zatem, to modne ostatnio okre lenie, strongly typed. Pozwala dzi ki
         temu na bezpieczny, tj. zachowuj cy typy danych, dost p do zewn trznego zasobu — do
         danych w bazie SQL Server.

         Nowe klasy TelefonyDataContext i ListaOsob mo na wykorzystaü tak, jak robili my
         do tej pory z klas Osoba i „r cznie” tworzon instancj klasy DataContext. Listing 3.7
         pokazuje kod metody, w której zmiany dotycz w zasadzie wyá cznie nazw klas: z wcze-
          niej u ywanych DataContext i Osoba na TelefonyDataContext i ListaOsob. Skorzy-
         staáem tak e z wáasno ci ListaOsobs (z „s” na ko cu) pierwszej z klas, aby pobraü re-
         ferencj do kolekcji zawieraj cej dane z tabeli ListaOsob (wyró nienie w listingu 3.7).

Listing 3.7. Korzystanie z automatycznie utworzonej klasy encji do pobierania i modyfikacji danych
z tabeli SQL Server
            private void button5_Click(object sender, EventArgs e)
            {
               //tworzenie obiektu DataContext i pobieranie danych z tabeli
               string nazwaPliku = "Telefony.mdf";
               nazwaPliku = Path.GetFullPath(nazwaPliku);
               if (!File.Exists(nazwaPliku))
               {
                  MessageBox.Show("Brak pliku " + nazwaPliku);
                  return;
               }
               TelefonyDataContext bazaDanychTelefony = new TelefonyDataContext(nazwaPliku);
               var listaOsob = bazaDanychTelefony.ListaOsobs;

                //pobieranie kolekcji
                var listaOsobPelnoletnich=from osoba in listaOsob where osoba.Wiek>=18 select osoba;

                //wy wietlanie pobranej kolekcji
                string s = "Lista osób pe noletnich:n";
                foreach (ListaOsob osoba in listaOsobPelnoletnich)
                   s += osoba.Imiú + " " + osoba.Nazwisko + " (" + osoba.Wiek + ")n";
                MessageBox.Show(s);

                //informacje o pobranych danych
                MessageBox.Show("Typ: " + listaOsobPelnoletnich.GetType().FullName);
                MessageBox.Show("Ilo è pobranych rekordów: " +
                                 ´listaOsobPelnoletnich.Count().ToString());
                MessageBox.Show("Suma wieku wybranych osób: "
                               ´+ listaOsobPelnoletnich.Sum(osoba => osoba.Wiek).ToString());
                MessageBox.Show("Imiú pierwszej osoby: " + listaOsobPelnoletnich.First().Imiú);

                s = "Pe na lista osób:n";
                foreach (ListaOsob osoba in listaOsob)
                   s += osoba.Imiú + " " + osoba.Nazwisko + " (" + osoba.Wiek + ")n";
                MessageBox.Show(s);
            }
Rozdziaä 3. i LINQ i SQL Server                                                            39


        Wspóäpraca z kontrolkami tworzñcymi interfejs aplikacji
        Ewidentnie nadu ywam metody MessageBox.Show. Bardziej naturalne do prezentacji
        danych jest oczywi cie korzystanie z kontrolek, np. DataGridView. Bez trudu mo na
        taki komponent wypeániü danymi udost pnianymi przez klas TelefonyDataContext.
        Dodajmy do projektu now form i zdefiniujmy w niej pole — instancj tej ostatniej
        klasy:
           TelefonyDataContext bazaDanychTelefony = new TelefonyDataContext();

        Nast pnie wystarczy umie ciü na formie kontrolk DataGridView i przypisaü jej wáa-
        sno ci DataSource odpowiedni tabel (np. w konstruktorze za poleceniem Initialize
        ´Component();):
           dataGridView1.DataSource = bazaDanychTelefony.ListaOsobs;

        Je eli nie chcemy prezentowaü peánej zawarto ci tabeli, wáasno ci DataSource mo emy
        przypisaü kolekcj zwracan przez zapytanie LINQ:
           dataGridView1.DataSource = from osoba in bazaDanychTelefony.ListaOsobs
                                      where osoba.Wiek >= 18
                                      orderby osoba.Imiú
                                      select new { osoba.Imiú, osoba.Nazwisko, osoba.Wiek };

        Kontrolka DataGridView pozwala na edycj danych z kolekcji, jednak pod warunkiem,
         e prezentowana w niej kolekcja nie jest zbudowana z obiektów anonimowych typów,
        lecz z referencji do obiektów ze ródáa danych (instancji klas encji):
           dataGridView1.DataSource = from osoba in bazaDanychTelefony.ListaOsobs
                                      where osoba.Wiek >= 18
                                      orderby osoba.Imiú
                                      select osoba;

        Aby wprowadzone w ten sposób modyfikacje danych wysáaü z powrotem do bazy,
        nale y tylko wywoáaü metod SubmitChanges instancji klasy TelefonyDataContext, tj.
        obiektu bazaDanychTelefony.

        Do formy mo emy dodaü tak e rozwijan list ComboBox. Mo emy „podá czyü” j do tego
        samego wi zania, którym z baz poá czona jest kontrolka dataGridView1. W tym celu
        do konstruktora nale y dopisaü dwa polecenia:
           comboBox1.DataSource = dataGridView1.DataSource;
           comboBox1.DisplayMember = "Imiú";

        Pierwsze wskazuje na ródáo danych rozwijanej listy — jest nim ta sam kolekcja, która
        prezentowana jest w kontrolce dataGridView1. Drugie precyzuje, któr kolumn da-
        nych rozwijana lista ma prezentowaü. Ze wzgl du na korzystanie ze wspólnego wi -
        zania zmiana aktywnego rekordu w siatce spowoduje zmian rekordu w rozwijanej li-
         cie i odwrotnie.
40                                                      C# 3.0 i .NET 3.5. Technologia LINQ


     Kreator ródäa danych i automatyczne tworzenie
     interfejsu u ytkownika
     Do utworzenia odpowiednich obiektów mo na jednak ponownie zaprz c Visual C#. Oczy-
     wi cie, w takim przypadku kod nie b dzie tak prosty i przejrzysty jak ten napisany sa-
     modzielnie, ale za to nie musimy go przygotowywaü i sprawdzaü sami. Cel, do którego
     d ymy, to utworzenie ródáa danych, takiego, do jakich przyzwyczaiáo nas ADO.NET.
     Jednak w tym przypadku czerpaü ono b dzie dane nie bezpo rednio z bazy danych,
     ale za pomoc LINQ to SQL, a wi c poprzez zaprojektowan w O/R Designerze klas
     TelefonyDataContext i towarzysz c jej klas encji. Dysponuj c takim ródáem, b -
     dziemy mogli wi zaü z danymi kontrolki, z których budujemy interfejs aplikacji.

     Wybierzmy z menu Data polecenie Add New Data Source…. Pojawi si kreator Data
     Source Configuration Wizard. W jego pierwszym kroku wybieramy ródáo danych (rysu-
     nek 3.3, górny); zaznaczmy ikon Object. Klikamy Next >. W nast pnym kroku wy-
     bieramy klas , która zawiera informacje na temat struktury tabeli ListaOsob (rysunek 3.3,
     dolny). W naszym przypadku jest to klasa ListaOsob. Wreszcie klikamy Finish.

     Po zamkni ciu kreatora wybierzmy polecenie Show Data Sources z menu Data. Pojawi
     si nowe podokno o nazwie Data Sources, w którym zobaczymy nowe, utworzone przed
     chwil ródáo danych. Mo emy sprawdziü jego pola — powinny odpowiadaü polom
     tabeli (rysunek 3.4). Tak zdefiniowane ródáo danych nie zawiera niestety samych da-
     nych, a jedynie informacje o ich strukturze. To jednak wystarczy, aby bardzo przyspie-
     szyü projektowanie interfejsu u ytkownika w aplikacjach bazodanowych.

     Gdy dysponujemy ródáem danych, mo emy zaprojektowaü interfejs aplikacji, korzy-
     staj c z metody „przeci gnij i upu ü”. Mo emy bowiem przeci gaü na form poszcze-
     gólne pola tabeli ListaOsob widoczne w podoknie Data Sources. Powstanie wówczas
     kontrolka z automatycznie dodanym opisem. Typ kontrolki, która powstanie, mo na
     wcze niej wybraü w rozwijanych listach zwi zanych z ka dym polem, w podoknie
     Data Sources (rysunek 3.4). Przeniesienie caáej tabeli spowoduje przy domy lnych usta-
     wieniach umieszczenie na formie siatki dataGridView. Jednak je eli wcze niej w pozycji
     ListaOsob (w podoknie Data Sources) z rozwijanej listy wybierzemy Details zamiast
     domy lnego DataGridView, zamiast siatki na formie umieszczony zostanie zbiór kon-
     trolek zgodnie z wyborem dla ka dego z pól. Wraz z pierwsz umieszczon w ten
     sposób kontrolk na formie pojawi si komponent wi zania (listaOsobBindingSource)
     oraz kontrolka nawigacyjna (listaOsobBindingNavigator). T ostatni mo emy zoba-
     czyü na szczycie podgl du formy na rysunku 3.4.

     Tak jak uprzedzaáem, ródáo danych nie zawiera danych, a jedynie informacje o ich
     strukturze. Zatem po skompilowaniu kontrolki nie b d prezentowaáy adnych sen-
     sownych informacji. Wystarczy jednak odpowiednio „podpi ü” kontrolk wi zania
     listaOsobBindingSource, aby wszystko zacz áo graü. Zaczynamy od zdefiniowania pola
     formy b d cego instancj naszej klasy reprezentuj cej baz danych:
       TelefonyDataContext bazaDanychTelefony = new TelefonyDataContext();
Rozdziaä 3. i LINQ i SQL Server                                                   41




Rysunek 3.3. Pierwszy krok kreatora obiektu — ródáa danych LINQ to SQL

        Nast pnie w konstruktorze wi emy udost pnian przez ten obiekt tabel ListaOsob
        z obiektem wi zania listaOsobBindingSource:
           listaOsobBindingSource.DataSource = bazaDanychTelefony.ListaOsobs;
42                                                         C# 3.0 i .NET 3.5. Technologia LINQ




Rysunek 3.4. Projektowanie interfejsu aplikacji na bazie ródáa danych LINQ

        Wszystkie wizualne kontrolki tworz ce interfejs u ytkownika zwi zane s z tym jed-
        nym obiektem wi zania, zatem zmiana aktualnego rekordu w którejkolwiek z nich spo-
        woduje automatyczn zmian widocznego rekordu w pozostaáych. Mo liwe jest oczy-
        wi cie zapisywanie zmian wprowadzonych za pomoc kontrolek. Wystarczy jedynie
        wywoáaü metod bazaDanychTelefony.SubmitChanges.

        ãñczenie danych z dwóch tabel — operator join
        Informacje o osobach mog byü umieszczone w kilku tabelach. Dla przykáadu w osob-
        nej tabeli mógáby byü umieszczony spis rozmów, jakie przeprowadzaáy osoby z tabeli
        ListaOsob. Tabela b dzie zawieraü identyfikator osoby, personalia jej rozmówcy, dat prze-
        prowadzenia rozmowy i jej czas trwania w minutach. Pola o nazwie Id i CzasTrwania
        b d typu int, pole Rozmowca — typu nvarchar(MAX), a pole Data — typu datetime.
          adne z pól nie b dzie dopuszczaü pustych warto ci. Kluczem gáównym mo emy uczyniü
        tylko pole Data. Zapiszmy tabel , nazywaj c j po prostu Rozmowy. Pole Id w nowej
        tabeli b dzie tym samym Id, którym identyfikowana jest osoba w tabeli ListaOsob.
        Zatem ka dej osobie b dzie mo na przyporz dkowaü list rozmów, a ka dej rozmowie
        — tylko jednego rozmówc . Tabela ListaOsob b dzie wi c nasz tabel -rodzicem, a ta-
        bela Rozmowy — tabel -dzieckiem. Tabel nale y oczywi cie wypeániü jakimi przy-
        káadowymi danymi (rysunek 3.5).

        Nast pnie przejd my na zakáadk Telefony.dbml i przenie my now tabel na lewy panel,
        obok tabeli ListaOsob. Do klasy TelefonyDataContext dodana zostanie nowa wáasno ü
        o nazwie Rozmowies (znowu nie dopasowali my si do proangielskiego schematu nazw).

        Pobierzmy teraz list rozmów trwaj cych dáu ej ni dziesi ü minut wraz z persona-
        liami dzwoni cej osoby. W tym celu zapytanie LINQ rozszerzymy o operator join,
        który pobieraü b dzie rekordy o tych samych warto ciach pól Id w obu tabelach. Po-
        kazuje to listing 3.8.
Rozdziaä 3. i LINQ i SQL Server                                                            43




Rysunek 3.5. Nowa tabela bazy Telefony.mdf

Listing 3.8. Pomin áem polecenia tworz ce obiekt bazaDanychTelefony

           var listaOsob = bazaDanychTelefony.ListaOsobs;
           var rozmowy = bazaDanychTelefony.Rozmowies;

           IEnumerable<string> listaDlugichRozmow =
              from osoba in listaOsob
              join rozmowa in rozmowy on osoba.Id equals rozmowa.Id
              where rozmowa.CzasTrwania > 10
              select osoba.Imiú + " " + osoba.Nazwisko + ", " + rozmowa.Data.ToString()
                 ´+" (" + rozmowa.CzasTrwania + ")";

           string s = "Lista rozmów trwajæcych d u ej ni 10 min:n";
           foreach (string opis in listaDlugichRozmow) s += opis + "n";
           MessageBox.Show(s);


        Relacje (Associations)
        Zamiast korzystaü z operatora join, mo emy poá czyü obie tabele w O/R Designerze.
        A w zasadzie nie tabele, tylko reprezentuj ce je klasy. Przejd my na zakáadk Telefony.
        ´dbml, kliknijmy prawym przyciskiem myszy nagáówek tabeli ListaOsob i z kontek-
        stowego menu wybierzmy polecenie Add, Association. Pojawi si edytor relacji (ry-
        sunek 3.6). Z rozwijanej listy Child Class wybieramy Rozmowy. Nast pnie w tabeli
        Association Properties pod spodem wybieramy w obu kolumnach pole Id.
44                                                       C# 3.0 i .NET 3.5. Technologia LINQ


Rysunek 3.6.
Edytor poá czenia
mi dzy obiektami
reprezentuj cymi
tabele




        Ustanowione poá czenie zaznaczone zostanie w O/R Designerze strzaák á cz c dwie
        tabele. W podobny sposób zaznaczone byáyby relacje mi dzy tabelami, które zdefi-
        niowane s w samej bazie danych. Skutek obu poá cze jest podobny.

        Dzi ki relacji á cz cej obie tabele mo emy upro ciü zapytanie LINQ:
           var listaDlugichRozmow = from rozmowa in rozmowy
                                    where rozmowa.CzasTrwania > 10
                                    select rozmowa.ListaOsob.Imiú + " " +
                                           ´rozmowa.ListaOsob.Nazwisko + ", " +
                                           ´rozmowa.Data.ToString() +
                                           ´" (" + rozmowa.CzasTrwania + ")"; ;

        Jest to mo liwe, poniewa do klasy encji Rozmowy dodana zostaáa wáasno ü ListaOsob,
        która wskazuje na jeden pasuj cy rekord tabeli ListaOsob. Z kolei klasa encji ListaOsob
        zawiera wáasno ü Rozmowies obejmuj c peáen zbiór rekordów, w których warto ü pola
        Id równa jest tej, jaka jest w bie cym wierszu tabeli ListaOsob. To ostatnie pozwala
        na proste filtrowanie danych bez konieczno ci przygotowywania zapytania LINQ. A wi c
        kolekcja uzyskana poleceniem:
           var listaRozmowKarolinyMatulewskiej =
              ´bazaDanychTelefony.ListaOsobs.Single(osoba => osoba.Id == 3).Rozmowies;

        zawiera identyczne rekordy jak uzyskana zapytaniem:
           var listaRozmowKarolinyMatulewskiej = from rozmowa in rozmowy
                                                 where rozmowa.Id == 3
                                                 select rozmowa;




Korzystanie z procedur skäadowanych
        W momencie uruchamiania metody SubmitChanges obiekt klasy DataContext automa-
        tycznie tworzy zbiór polece SQL, które modyfikuj zawarto ü bazy danych. Podob-
        nie jest zreszt w momencie pobierania danych. Wówczas zapytanie LINQ jest táuma-
        czone na zapytanie SQL i wysyáane do bazy danych.
Rozdziaä 3. i LINQ i SQL Server                                                           45


        Zamiast korzystaü z tych tworzonych automatycznie procedur i zapyta mo emy wy-
        korzystaü wáasne procedury skáadowane w bazie danych (ang. stored procedures). Jest
        to w pewnym sensie krok wstecz, wymaga bowiem programowania w SQL, ale za to po-
        zwala na zachowanie peánej elastyczno ci podczas korzystania z SQL Server. I nawet
        je eli z procedur skáadowych nie b dziemy korzystaü do pobierania danych, warto je
        poznaü, aby móc uruchamiaü dowolne polecenia SQL, które pozwol nam np. tworzyü
        nowe tabele w bazie.

        Pobieranie danych za pomocñ procedur skäadowanych
        Utwórzmy i zapiszmy w bazie danych zapytanie pobieraj ce personalia osób peánoletnich
        zapisanych w tabeli ListaOsob. W tym celu otwórzmy plik Telefony.mdf w Database
        Explorer, przejd my do pozycji Stored Procedures i prawym przyciskiem myszy roz-
        wi my jej menu kontekstowe. Wybierzmy z niego polecenie Add New Stored Procedure.

        Pojawi si edytor, w którym mo emy wpisaü kod SQL (rysunek 3.7). Za sáowem kluczo-
        wym AS wpiszmy proste zapytanie SQL: SELECT * FROM ListaOsob WHERE Wiek>=18.
        Zmie my te nazw procedury na dbo.ListaOsobPelnoletnich. Wreszcie zapiszmy zmiany
        w bazie danych (Ctrl+S). W podoknie Database Explorer, w gaá zi Stored Procedures
        bazy Telefony.mdf, powinna pojawiü si pozycja ListaOsobPelnoletnich. Mo emy wów-
        czas przej ü na zakáadk Telefony.dbml i przeci gn ü procedur z podokna Database
        Explorer do pustego panelu po prawej stronie. To spowoduje dodanie do klasy Telefony
        ´DataContext metody ListaOsobPelnoletnich. Zwraca ona dane pobrane przez za-
        pytanie SQL w postaci kolekcji elementów typu ListaOsobPelnoletnichResult.




Rysunek 3.7. Edycja zapytania SQL procedury umieszczonej w bazie danych

        Typ ListaOsobPelnoletnichResult zostaá automatycznie utworzony za pomoc O/R
        Designera. W przypadku pobierania wszystkich pól z tabeli, tj. gdy w zapytaniu SQL
        po sáowie SELECT widoczna jest gwiazdka (*), nowa klasa b dzie równowa na typowi
        ListaOsob (i Osoba). Zapytanie SQL mo e jednak zwracaü tylko wybrane pola, a wów-
        czas tworzenie nowego typu jest bardziej przydatne.
46                                                         C# 3.0 i .NET 3.5. Technologia LINQ


        Dzi ki nowej metodzie uruchomienie skáadowanego zapytania SQL i odebranie zwra-
        canych przez nie danych jest dziecinnie proste:
           IEnumerable<ListaOsobPelnoletnichResult> listaOsobPelnoletnich =
              ´bazaDanychTelefony.ListaOsobPelnoletnich();


        Modyfikowanie danych za pomocñ procedur skäadowanych
        Przygotujmy teraz procedur skáadowan zwi kszaj c o jeden wiek wszystkich osób
        nieb d cych peánoletnimi kobietami (listing 3.9). Zapiszmy j w bazie pod nazw
        AktualizujWiek i dodajmy do prawego panelu na zakáadce Telefony.dbml.

Listing 3.9. Procedura skáadowana modyfikuj ca dane w tabeli ListaOsob
           ALTER PROCEDURE dbo.AktualizujWiek
           AS
           UPDATE ListaOsob SET Wiek=Wiek+1 WHERE NOT SUBSTRING(Imiú,LEN(Imiú),1)='a' OR Wiek<18
            RETURN


        Aby j uruchomiü z poziomu C#, wystarczy do kodu dodaü instrukcj :
           bazaDanychTelefony.AktualizujWiek();

        Zmiany w tabeli bazy danych b d wprowadzone natychmiast i bezpo rednio, tj. np.
        bez konieczno ci uruchamiania metody SubmitChanges instancji TelefonyDataContext.
        Z tego wynika te , e je eli wcze niej pobrali my kolekcj danych zapytaniem LINQ,
        nale y to teraz powtórzyü, aby uwzgl dniü aktualizacje.

        Wykonywanie dowolnych poleceþ SQL
        Pobieranie danych i ich modyfikacja za pomoc skáadowanych polece SQL nie jest
        mo e tym, co programi ci znaj cy LINQ zbytnio doceniaj . Warto jednak zwróciü
        uwag , e istnieje grupa czynno ci, które w SQL jest wykonaü najpro ciej. Przyjmijmy,
         e w naszej bazie danych tworzymy zbiór tabel dla ka dego nowego zarejestrowanego
        u ytkownika. Wówczas nie do przecenienia jest mo liwo ü przygotowania skáadowanej
        procedury zawieraj cej kod SQL tworz cy tabel i wypeániaj cy j danymi. W tym celu
        wystarczy dodaü now procedur skáadow (przykáad widoczny jest na listingu 3.10),
        dodaü j za pomoc O/R Designera do klasy TelefonyDataContext i wywoáaü w ko-
        dzie C#. Nazw i dane tabeli mo emy przekazaü przez parametry procedury. Pami -
        tajmy jednak, e nowa utworzona w ten sposób tabela nie b dzie zmapowana i w kon-
        sekwencji nie b dzie widoczna w obiekcie — instancji klasy TelefonyDataContext.

Listing 3.10. Przykáadowa procedura skáadowa tworz ca tabel
           ALTER PROCEDURE dbo.TwórzNowæTabelú
           AS
           CREATE TABLE "Faktury" (Id INT, NrFaktury INT, Opis NVARCHAR(MAX))
           INSERT INTO "Faktury" VALUES(1, 1022, 'Faktura za stycze 2008')
           INSERT INTO "Faktury" VALUES(1, 1022, 'Faktura za luty 2008')
            RETURN

Mais conteúdo relacionado

Destaque

Negocjacje dla prawników. Prawo cywilne - ebook
Negocjacje dla prawników. Prawo cywilne - ebookNegocjacje dla prawników. Prawo cywilne - ebook
Negocjacje dla prawników. Prawo cywilne - ebooke-booksweb.pl
 
Internet – jak wykorzystać jego potencjał w usługach turystycznych. Szanse, ...
 Internet – jak wykorzystać jego potencjał w usługach turystycznych. Szanse, ... Internet – jak wykorzystać jego potencjał w usługach turystycznych. Szanse, ...
Internet – jak wykorzystać jego potencjał w usługach turystycznych. Szanse, ...Bartłomiej Juszczyk
 
Kwestia cypryjska po roku 2004 pojednanie czy podział?
Kwestia cypryjska po roku 2004 pojednanie czy podział?Kwestia cypryjska po roku 2004 pojednanie czy podział?
Kwestia cypryjska po roku 2004 pojednanie czy podział?Przemyslaw Osiewicz
 
Opinia Publiczna Invenview
Opinia Publiczna InvenviewOpinia Publiczna Invenview
Opinia Publiczna Invenviewj.dobi
 
Subkultury i ich przemiany
Subkultury i ich przemianySubkultury i ich przemiany
Subkultury i ich przemianykassia-89
 
The international system
The international systemThe international system
The international systemDoctor_Rock
 
CorelDRAW 11. Vademecum profesjonalisty. Tom 2
CorelDRAW 11. Vademecum profesjonalisty. Tom 2CorelDRAW 11. Vademecum profesjonalisty. Tom 2
CorelDRAW 11. Vademecum profesjonalisty. Tom 2Wydawnictwo Helion
 
Aukcje internetowe-i-co-dalej
Aukcje internetowe-i-co-dalejAukcje internetowe-i-co-dalej
Aukcje internetowe-i-co-daleje-book prezenty
 
Dochody ze swiadczen
Dochody ze swiadczenDochody ze swiadczen
Dochody ze swiadczeniwsz1
 
Problemy związane z pomiarem przestępczości - ebook
Problemy związane z pomiarem przestępczości - ebookProblemy związane z pomiarem przestępczości - ebook
Problemy związane z pomiarem przestępczości - ebooke-booksweb.pl
 
Kształtowanie kultury organizacyjnej w służbie cywilnej Radosław Sidor, Mat...
Kształtowanie kultury organizacyjnej w służbie cywilnej   Radosław Sidor, Mat...Kształtowanie kultury organizacyjnej w służbie cywilnej   Radosław Sidor, Mat...
Kształtowanie kultury organizacyjnej w służbie cywilnej Radosław Sidor, Mat...BrazaAKABoss
 

Destaque (15)

Negocjacje dla prawników. Prawo cywilne - ebook
Negocjacje dla prawników. Prawo cywilne - ebookNegocjacje dla prawników. Prawo cywilne - ebook
Negocjacje dla prawników. Prawo cywilne - ebook
 
Biuletyn ERP dzisiaj. Nr 1
Biuletyn ERP dzisiaj. Nr 1Biuletyn ERP dzisiaj. Nr 1
Biuletyn ERP dzisiaj. Nr 1
 
2011 03 30_projekt_ustawy
2011 03 30_projekt_ustawy2011 03 30_projekt_ustawy
2011 03 30_projekt_ustawy
 
Internet – jak wykorzystać jego potencjał w usługach turystycznych. Szanse, ...
 Internet – jak wykorzystać jego potencjał w usługach turystycznych. Szanse, ... Internet – jak wykorzystać jego potencjał w usługach turystycznych. Szanse, ...
Internet – jak wykorzystać jego potencjał w usługach turystycznych. Szanse, ...
 
Łukasz Dąbrowiecki - Uczestniczenie w praktyce
Łukasz Dąbrowiecki - Uczestniczenie w praktyceŁukasz Dąbrowiecki - Uczestniczenie w praktyce
Łukasz Dąbrowiecki - Uczestniczenie w praktyce
 
Kwestia cypryjska po roku 2004 pojednanie czy podział?
Kwestia cypryjska po roku 2004 pojednanie czy podział?Kwestia cypryjska po roku 2004 pojednanie czy podział?
Kwestia cypryjska po roku 2004 pojednanie czy podział?
 
Opinia Publiczna Invenview
Opinia Publiczna InvenviewOpinia Publiczna Invenview
Opinia Publiczna Invenview
 
Subkultury i ich przemiany
Subkultury i ich przemianySubkultury i ich przemiany
Subkultury i ich przemiany
 
The international system
The international systemThe international system
The international system
 
CorelDRAW 11. Vademecum profesjonalisty. Tom 2
CorelDRAW 11. Vademecum profesjonalisty. Tom 2CorelDRAW 11. Vademecum profesjonalisty. Tom 2
CorelDRAW 11. Vademecum profesjonalisty. Tom 2
 
Aukcje internetowe-i-co-dalej
Aukcje internetowe-i-co-dalejAukcje internetowe-i-co-dalej
Aukcje internetowe-i-co-dalej
 
Dochody ze swiadczen
Dochody ze swiadczenDochody ze swiadczen
Dochody ze swiadczen
 
11
1111
11
 
Problemy związane z pomiarem przestępczości - ebook
Problemy związane z pomiarem przestępczości - ebookProblemy związane z pomiarem przestępczości - ebook
Problemy związane z pomiarem przestępczości - ebook
 
Kształtowanie kultury organizacyjnej w służbie cywilnej Radosław Sidor, Mat...
Kształtowanie kultury organizacyjnej w służbie cywilnej   Radosław Sidor, Mat...Kształtowanie kultury organizacyjnej w służbie cywilnej   Radosław Sidor, Mat...
Kształtowanie kultury organizacyjnej w służbie cywilnej Radosław Sidor, Mat...
 

Semelhante a C# 3.0 i .NET 3.5. Technologia LINQ

MySQL. Budowanie interfejsów użytkownika. Vademecum profesjonalisty
MySQL. Budowanie interfejsów użytkownika. Vademecum profesjonalistyMySQL. Budowanie interfejsów użytkownika. Vademecum profesjonalisty
MySQL. Budowanie interfejsów użytkownika. Vademecum profesjonalistyWydawnictwo Helion
 
PHP. 101 praktycznych skryptów. Wydanie II
PHP. 101 praktycznych skryptów. Wydanie IIPHP. 101 praktycznych skryptów. Wydanie II
PHP. 101 praktycznych skryptów. Wydanie IIWydawnictwo Helion
 
ASP.NET 2.0. Gotowe rozwiązania
ASP.NET 2.0. Gotowe rozwiązaniaASP.NET 2.0. Gotowe rozwiązania
ASP.NET 2.0. Gotowe rozwiązaniaWydawnictwo Helion
 
Visual C# 2005. Zapiski programisty
Visual C# 2005. Zapiski programistyVisual C# 2005. Zapiski programisty
Visual C# 2005. Zapiski programistyWydawnictwo Helion
 
C++. Wykorzystaj potęgę aplikacji graficznych
C++. Wykorzystaj potęgę aplikacji graficznychC++. Wykorzystaj potęgę aplikacji graficznych
C++. Wykorzystaj potęgę aplikacji graficznychWydawnictwo Helion
 
.NET Framework 2.0. Zaawansowane programowanie
.NET Framework 2.0. Zaawansowane programowanie.NET Framework 2.0. Zaawansowane programowanie
.NET Framework 2.0. Zaawansowane programowanieWydawnictwo Helion
 
Struktury danych i techniki obiektowe na przykładzie Javy 5.0
Struktury danych i techniki obiektowe na przykładzie Javy 5.0Struktury danych i techniki obiektowe na przykładzie Javy 5.0
Struktury danych i techniki obiektowe na przykładzie Javy 5.0Wydawnictwo Helion
 
PHP i MySQL. Dynamiczne strony WWW. Szybki start
PHP i MySQL. Dynamiczne strony WWW. Szybki startPHP i MySQL. Dynamiczne strony WWW. Szybki start
PHP i MySQL. Dynamiczne strony WWW. Szybki startWydawnictwo Helion
 
Excel 2003. Programowanie. Zapiski programisty
Excel 2003. Programowanie. Zapiski programistyExcel 2003. Programowanie. Zapiski programisty
Excel 2003. Programowanie. Zapiski programistyWydawnictwo Helion
 
Core Java Servlets i JavaServer Pages. Tom II. Wydanie II
Core Java Servlets i JavaServer Pages. Tom II. Wydanie IICore Java Servlets i JavaServer Pages. Tom II. Wydanie II
Core Java Servlets i JavaServer Pages. Tom II. Wydanie IIWydawnictwo Helion
 
Delphi. Techniki bazodanowe i internetowe
Delphi. Techniki bazodanowe i internetoweDelphi. Techniki bazodanowe i internetowe
Delphi. Techniki bazodanowe i internetoweWydawnictwo Helion
 
SQL Server 2005. Wyciśnij wszystko
SQL Server 2005. Wyciśnij wszystkoSQL Server 2005. Wyciśnij wszystko
SQL Server 2005. Wyciśnij wszystkoWydawnictwo Helion
 
Bazy danych SQL. Teoria i praktyka
Bazy danych SQL. Teoria i praktykaBazy danych SQL. Teoria i praktyka
Bazy danych SQL. Teoria i praktykaWydawnictwo Helion
 

Semelhante a C# 3.0 i .NET 3.5. Technologia LINQ (20)

MySQL. Budowanie interfejsów użytkownika. Vademecum profesjonalisty
MySQL. Budowanie interfejsów użytkownika. Vademecum profesjonalistyMySQL. Budowanie interfejsów użytkownika. Vademecum profesjonalisty
MySQL. Budowanie interfejsów użytkownika. Vademecum profesjonalisty
 
PHP. 101 praktycznych skryptów. Wydanie II
PHP. 101 praktycznych skryptów. Wydanie IIPHP. 101 praktycznych skryptów. Wydanie II
PHP. 101 praktycznych skryptów. Wydanie II
 
ASP.NET 2.0. Gotowe rozwiązania
ASP.NET 2.0. Gotowe rozwiązaniaASP.NET 2.0. Gotowe rozwiązania
ASP.NET 2.0. Gotowe rozwiązania
 
Visual C# 2005. Zapiski programisty
Visual C# 2005. Zapiski programistyVisual C# 2005. Zapiski programisty
Visual C# 2005. Zapiski programisty
 
MySQL
MySQLMySQL
MySQL
 
C++. Wykorzystaj potęgę aplikacji graficznych
C++. Wykorzystaj potęgę aplikacji graficznychC++. Wykorzystaj potęgę aplikacji graficznych
C++. Wykorzystaj potęgę aplikacji graficznych
 
.NET Framework 2.0. Zaawansowane programowanie
.NET Framework 2.0. Zaawansowane programowanie.NET Framework 2.0. Zaawansowane programowanie
.NET Framework 2.0. Zaawansowane programowanie
 
C# i .NET
C# i .NETC# i .NET
C# i .NET
 
Linux w sieci
Linux w sieciLinux w sieci
Linux w sieci
 
Delphi 7 i bazy danych
Delphi 7 i bazy danychDelphi 7 i bazy danych
Delphi 7 i bazy danych
 
Struktury danych i techniki obiektowe na przykładzie Javy 5.0
Struktury danych i techniki obiektowe na przykładzie Javy 5.0Struktury danych i techniki obiektowe na przykładzie Javy 5.0
Struktury danych i techniki obiektowe na przykładzie Javy 5.0
 
PHP i MySQL. Dynamiczne strony WWW. Szybki start
PHP i MySQL. Dynamiczne strony WWW. Szybki startPHP i MySQL. Dynamiczne strony WWW. Szybki start
PHP i MySQL. Dynamiczne strony WWW. Szybki start
 
Excel 2003. Programowanie. Zapiski programisty
Excel 2003. Programowanie. Zapiski programistyExcel 2003. Programowanie. Zapiski programisty
Excel 2003. Programowanie. Zapiski programisty
 
Core Java Servlets i JavaServer Pages. Tom II. Wydanie II
Core Java Servlets i JavaServer Pages. Tom II. Wydanie IICore Java Servlets i JavaServer Pages. Tom II. Wydanie II
Core Java Servlets i JavaServer Pages. Tom II. Wydanie II
 
Delphi. Techniki bazodanowe i internetowe
Delphi. Techniki bazodanowe i internetoweDelphi. Techniki bazodanowe i internetowe
Delphi. Techniki bazodanowe i internetowe
 
Linux. Leksykon kieszonkowy
Linux. Leksykon kieszonkowyLinux. Leksykon kieszonkowy
Linux. Leksykon kieszonkowy
 
SQL Server 2005. Wyciśnij wszystko
SQL Server 2005. Wyciśnij wszystkoSQL Server 2005. Wyciśnij wszystko
SQL Server 2005. Wyciśnij wszystko
 
Bazy danych SQL. Teoria i praktyka
Bazy danych SQL. Teoria i praktykaBazy danych SQL. Teoria i praktyka
Bazy danych SQL. Teoria i praktyka
 
.NET CLR. Księga eksperta
.NET CLR. Księga eksperta.NET CLR. Księga eksperta
.NET CLR. Księga eksperta
 
SQL. Szybki start
SQL. Szybki startSQL. Szybki start
SQL. Szybki start
 

Mais de Wydawnictwo Helion

Tworzenie filmów w Windows XP. Projekty
Tworzenie filmów w Windows XP. ProjektyTworzenie filmów w Windows XP. Projekty
Tworzenie filmów w Windows XP. ProjektyWydawnictwo Helion
 
Blog, więcej niż internetowy pamiętnik
Blog, więcej niż internetowy pamiętnikBlog, więcej niż internetowy pamiętnik
Blog, więcej niż internetowy pamiętnikWydawnictwo Helion
 
Pozycjonowanie i optymalizacja stron WWW. Ćwiczenia praktyczne
Pozycjonowanie i optymalizacja stron WWW. Ćwiczenia praktycznePozycjonowanie i optymalizacja stron WWW. Ćwiczenia praktyczne
Pozycjonowanie i optymalizacja stron WWW. Ćwiczenia praktyczneWydawnictwo Helion
 
E-wizerunek. Internet jako narzędzie kreowania image&#39;u w biznesie
E-wizerunek. Internet jako narzędzie kreowania image&#39;u w biznesieE-wizerunek. Internet jako narzędzie kreowania image&#39;u w biznesie
E-wizerunek. Internet jako narzędzie kreowania image&#39;u w biznesieWydawnictwo Helion
 
Microsoft Visual C++ 2008. Tworzenie aplikacji dla Windows
Microsoft Visual C++ 2008. Tworzenie aplikacji dla WindowsMicrosoft Visual C++ 2008. Tworzenie aplikacji dla Windows
Microsoft Visual C++ 2008. Tworzenie aplikacji dla WindowsWydawnictwo Helion
 
Co potrafi Twój iPhone? Podręcznik użytkownika. Wydanie II
Co potrafi Twój iPhone? Podręcznik użytkownika. Wydanie IICo potrafi Twój iPhone? Podręcznik użytkownika. Wydanie II
Co potrafi Twój iPhone? Podręcznik użytkownika. Wydanie IIWydawnictwo Helion
 
Makrofotografia. Magia szczegółu
Makrofotografia. Magia szczegółuMakrofotografia. Magia szczegółu
Makrofotografia. Magia szczegółuWydawnictwo Helion
 
Java. Efektywne programowanie. Wydanie II
Java. Efektywne programowanie. Wydanie IIJava. Efektywne programowanie. Wydanie II
Java. Efektywne programowanie. Wydanie IIWydawnictwo Helion
 
Ajax, JavaScript i PHP. Intensywny trening
Ajax, JavaScript i PHP. Intensywny treningAjax, JavaScript i PHP. Intensywny trening
Ajax, JavaScript i PHP. Intensywny treningWydawnictwo Helion
 
PowerPoint 2007 PL. Seria praktyk
PowerPoint 2007 PL. Seria praktykPowerPoint 2007 PL. Seria praktyk
PowerPoint 2007 PL. Seria praktykWydawnictwo Helion
 
Serwisy społecznościowe. Budowa, administracja i moderacja
Serwisy społecznościowe. Budowa, administracja i moderacjaSerwisy społecznościowe. Budowa, administracja i moderacja
Serwisy społecznościowe. Budowa, administracja i moderacjaWydawnictwo Helion
 

Mais de Wydawnictwo Helion (20)

Tworzenie filmów w Windows XP. Projekty
Tworzenie filmów w Windows XP. ProjektyTworzenie filmów w Windows XP. Projekty
Tworzenie filmów w Windows XP. Projekty
 
Blog, więcej niż internetowy pamiętnik
Blog, więcej niż internetowy pamiętnikBlog, więcej niż internetowy pamiętnik
Blog, więcej niż internetowy pamiętnik
 
Access w biurze i nie tylko
Access w biurze i nie tylkoAccess w biurze i nie tylko
Access w biurze i nie tylko
 
Pozycjonowanie i optymalizacja stron WWW. Ćwiczenia praktyczne
Pozycjonowanie i optymalizacja stron WWW. Ćwiczenia praktycznePozycjonowanie i optymalizacja stron WWW. Ćwiczenia praktyczne
Pozycjonowanie i optymalizacja stron WWW. Ćwiczenia praktyczne
 
E-wizerunek. Internet jako narzędzie kreowania image&#39;u w biznesie
E-wizerunek. Internet jako narzędzie kreowania image&#39;u w biznesieE-wizerunek. Internet jako narzędzie kreowania image&#39;u w biznesie
E-wizerunek. Internet jako narzędzie kreowania image&#39;u w biznesie
 
Microsoft Visual C++ 2008. Tworzenie aplikacji dla Windows
Microsoft Visual C++ 2008. Tworzenie aplikacji dla WindowsMicrosoft Visual C++ 2008. Tworzenie aplikacji dla Windows
Microsoft Visual C++ 2008. Tworzenie aplikacji dla Windows
 
Co potrafi Twój iPhone? Podręcznik użytkownika. Wydanie II
Co potrafi Twój iPhone? Podręcznik użytkownika. Wydanie IICo potrafi Twój iPhone? Podręcznik użytkownika. Wydanie II
Co potrafi Twój iPhone? Podręcznik użytkownika. Wydanie II
 
Makrofotografia. Magia szczegółu
Makrofotografia. Magia szczegółuMakrofotografia. Magia szczegółu
Makrofotografia. Magia szczegółu
 
Windows PowerShell. Podstawy
Windows PowerShell. PodstawyWindows PowerShell. Podstawy
Windows PowerShell. Podstawy
 
Java. Efektywne programowanie. Wydanie II
Java. Efektywne programowanie. Wydanie IIJava. Efektywne programowanie. Wydanie II
Java. Efektywne programowanie. Wydanie II
 
JavaScript. Pierwsze starcie
JavaScript. Pierwsze starcieJavaScript. Pierwsze starcie
JavaScript. Pierwsze starcie
 
Ajax, JavaScript i PHP. Intensywny trening
Ajax, JavaScript i PHP. Intensywny treningAjax, JavaScript i PHP. Intensywny trening
Ajax, JavaScript i PHP. Intensywny trening
 
PowerPoint 2007 PL. Seria praktyk
PowerPoint 2007 PL. Seria praktykPowerPoint 2007 PL. Seria praktyk
PowerPoint 2007 PL. Seria praktyk
 
Excel 2007 PL. Seria praktyk
Excel 2007 PL. Seria praktykExcel 2007 PL. Seria praktyk
Excel 2007 PL. Seria praktyk
 
Access 2007 PL. Seria praktyk
Access 2007 PL. Seria praktykAccess 2007 PL. Seria praktyk
Access 2007 PL. Seria praktyk
 
Word 2007 PL. Seria praktyk
Word 2007 PL. Seria praktykWord 2007 PL. Seria praktyk
Word 2007 PL. Seria praktyk
 
Serwisy społecznościowe. Budowa, administracja i moderacja
Serwisy społecznościowe. Budowa, administracja i moderacjaSerwisy społecznościowe. Budowa, administracja i moderacja
Serwisy społecznościowe. Budowa, administracja i moderacja
 
AutoCAD 2008 i 2008 PL
AutoCAD 2008 i 2008 PLAutoCAD 2008 i 2008 PL
AutoCAD 2008 i 2008 PL
 
Bazy danych. Pierwsze starcie
Bazy danych. Pierwsze starcieBazy danych. Pierwsze starcie
Bazy danych. Pierwsze starcie
 
Inventor. Pierwsze kroki
Inventor. Pierwsze krokiInventor. Pierwsze kroki
Inventor. Pierwsze kroki
 

C# 3.0 i .NET 3.5. Technologia LINQ

  • 1. C# 3.0 i .NET 3.5. Technologia LINQ Autor: Jacek Matulewski ISBN: 83-246-1447-8 Format: 158x235, stron: 88 Poznaj technologiê LINQ aby uzyskaæ swobodny dostêp do danych z SQL Server, pliku XML lub kolekcji z poziomu swoich programów • Bezpieczny dostêp do danych przy zachowaniu kontroli typów • Tworzenie zapytañ LINQ • Budowanie, analiza i pobieranie danych z plików XML Zastosowanie technologii LINQ (ang. Language-Integrated Query, zintegrowany jêzyk zapytañ) w zasadniczy sposób upraszcza projektowanie aplikacji bazodanowych. Zapytanie LINQ zwraca kolekcjê z przestrzeni nazw typów ogólnych. Kolekcja ta mo¿e byæ modyfikowana, a nastêpnie zwrócona do Ÿród³a. Dziêki temu zachowywana jest pe³na kontrola typów danych i ich konwersji w poszczególnych mechanizmach poœrednicz¹cych w pobieraniu danych. Ksi¹¿ka „C# 3.0 i .NET 3.5. Technologia LINQ” prezentuje prosty sposób korzystania ze zintegrowanego jêzyka zapytañ. Dziêki temu podrêcznikowi nauczysz siê pobieraæ dane z ró¿nego rodzaju Ÿróde³; tworzyæ pliki XML w nowy, bardziej intuicyjny sposób; stosowaæ sk³adowane rozszerzenia ? nowego typu metody (oraz odpowiadaj¹ce im operatory), zdefiniowane w najnowszej wersji jêzyka C#. Ponadto dowiesz siê, jak tworzyæ w³asne Ÿród³a danych LINQ. Krótko mówi¹c, z ksi¹¿k¹ „C# 3.0 i .NET 3.5. Technologia LINQ” nawet jako œrednio zaawansowany programista poradzisz sobie ze stworzeniem bardzo skomplikowanych aplikacji bazodanowych. • Wyra¿enia Lambda • Nowe operatory LINQ • Zapytania LINQ • LINQ to DataSet • Aktualizacja danych w bazie • Korzystanie z rozszerzeñ Wydawnictwo Helion • Kontrolka LinqDataSource ul. Koœciuszki 1c • Tworzenie i modyfikacja pliku XML 44-100 Gliwice • Tworzenie Ÿróde³ danych LINQ tel. 032 230 98 63 Ta ksi¹¿ka wska¿e Ci prosty sposób tworzenia doskona³ych e-mail: helion@helion.pl i nowoczesnych aplikacji bazodanowych
  • 2. Spis tre ci Wstöp .............................................................................................. 5 Rozdziaä 1. Nowo ci jözyka C# 3.0 ..................................................................... 7 Okre lanie typu zmiennej lokalnej przy inicjalizacji ........................................................ 7 Wyra enia Lambda ........................................................................................................... 8 Rozszerzenia ................................................................................................................... 10 Nowa forma inicjalizacji obiektów i tablic ..................................................................... 12 Nowe operatory LINQ .................................................................................................... 13 Typy anonimowe ............................................................................................................ 14 Przykáad — kolekcja jako ródáo danych ....................................................................... 14 Rozdziaä 2. LINQ i ADO.NET .............................................................................. 21 Konfiguracja kontrolki DataSet ...................................................................................... 22 LINQ to DataSet, czyli tam i z powrotem .......................................................................... 24 Korzy ci z LINQ to DataSet ........................................................................................... 26 Rozdziaä 3. LINQ i SQL Server ........................................................................... 29 Klasa encji ...................................................................................................................... 29 Pobieranie danych .......................................................................................................... 31 Aktualizacja danych w bazie .......................................................................................... 32 Wizualne projektowanie klasy encji ............................................................................... 35 Korzystanie z procedur skáadowanych ........................................................................... 44 Kontrolka LinqDataSource (ASP.NET) ......................................................................... 47 Rozdziaä 4. LINQ i XML .................................................................................... 51 Tworzenie pliku XML za pomoc klas XDocument i XElement ................................... 51 Pobieranie warto ci z elementów o znanej pozycji w drzewie ....................................... 54 Przenoszenie danych z kolekcji do pliku XML .............................................................. 55 Przenoszenie danych z bazy danych (komponentu DataSet) do pliku XML .................. 56 Zapytania LINQ .............................................................................................................. 57 Modyfikacja pliku XML ................................................................................................. 59 Rozdziaä 5. Tworzenie ródeä danych LINQ ......................................................... 61 IEnumerable ................................................................................................................... 61 IEnumerable<T> ............................................................................................................ 63 Oddzielenie ródáa od jego interfejsu ............................................................................. 65 IQueryable i IOrderedQueryable .................................................................................... 68
  • 3. 4 C# 3.0 i .NET 3.5. Technologia LINQ IQueryable<T> i IOrderedQueryable<T> ...................................................................... 69 Drzewo wyra enia .......................................................................................................... 71 Zadanie. LINQ to TXT ................................................................................................... 78 Dodatek A Wiöcej w sieci… ............................................................................ 83 Skorowidz ...................................................................................... 85
  • 4. Rozdziaä 3. LINQ i SQL Server Wspominaj c o technologii LINQ, mówi si zazwyczaj o zanurzeniu j zyka SQL w j - zyku C#. W przypadku LINQ to SQL zanurzenie to mo na rozumieü niemal dosáownie — zapytanie LINQ jest w tym przypadku táumaczone bezpo rednio na zapytanie SQL wysyáane do bazy danych. Zacznijmy od prostej sytuacji: poá czmy si z baz danych Telefony.mdf (zob. rysunek 2.3 z poprzedniego rozdziaáu) i pobierzmy z niej list osób peánoletnich. Wykorzystamy do tego obiekt klasy DataContext, która jak na razie wspóápracuje tylko z bazami SQL Server (nie dotyczy to jednak lokalnych baz SQL Server Compact Edition). Klasa DataContext jest gáówn bram do technologii LINQ to SQL. Brama ta wymaga jednak stra nika. Jego rol przejmuje klasa encji, tj. klasa C#, która zdefiniuje typ ka dego rekordu (encji) tabeli bazy danych. Dzi ki tej klasie mo liwe jest zbudowanie pomostu mi dzy tabel pobie- ran za pomoc zapytania SQL a kolekcj zwracan przez zapytanie LINQ, tj. mi dzy typem encji a typem elementu kolekcji. Dzi ki tej klasie w zapytaniu LINQ mo emy u ywaü nazw pól, które obecne s w tabeli, wr cz identyfikowaü kolekcj z tabel . Zanim przejdziemy do konkretów, chciaábym jeszcze zwróciü uwag Czytelnika na je- den istotny fakt. W LINQ to Object, które poznali my w pierwszym rozdziale, ródáem danych byáa kolekcja istniej ca w pami ci i w peáni dost pna z poziomu programu. Nie byáo zatem konieczno ci odwoáywania do zasobów zewn trznych (np. plików bazy danych). Dzi ki temu caáy kod aplikacji mógá byü skompilowany do kodu po redniego. W przy- padku LINQ to SQL, którym zajmiemy si w tym rozdziale, lub LINQ to XML, omówio- nego w kolejnym rozdziale, taka peána kompilacja nie jest mo liwa. Analiza danych pobranych ze ródáa danych mo e odbyü si dopiero w trakcie dziaáania programu. Realizowane jest to za pomoc drzewa zapyta , które poznamy dokáadniej w ostatnim rozdziale, przy okazji projektowania wáasnego ródáa danych LINQ. Klasa encji Klasa encji (ang. entity class) to zwykáa klasa C#, w której za pomoc atrybutów po- wi zane s pola klasy z polami tabeli (kolumnami). Mamy wi c do czynienia z mode- lowaniem zawarto ci relacyjnej bazy danych w typowanych klasach j zyka, w którym
  • 5. 30 C# 3.0 i .NET 3.5. Technologia LINQ przygotowujemy program. W tym kontek cie u ywany jest angielski termin strongly typed, który podkre la izomorficzno ü relacji klasy encji i struktury tabeli. Ów zwi - zek jest niezwykle istotny — przede wszystkim umo liwia kontrol typów, która w pewnym sensie rozci ga si na poá czenie z baz danych. Dzi ki tej relacji progra- mista mo e w pewnym stopniu uto samiaü t klas i reprezentowan przez ni tabel . To pozwala równie przygotowywaü zapytania LINQ, korzystaj c z nazw pól tabeli — jego táumaczenie na zapytanie SQL jest dzi ki temu szczególnie proste, a jedno- cze nie w peáni zachowana jest kontrola typów. Domy lne wi zanie realizowane jest na podstawie nazw obu pól. Mo liwa jest jednak zmiana tego domy lnego sposobu wi zania oraz zmiana wáasno ci poszczególnych pól. Przed caá klas znale ü si powinien atrybut Table z przestrzeni nazw System.Data. ´Linq.Mapping, w którym wskazujemy nazw tabeli z bazy danych1. Natomiast przed polami odpowiadaj cymi kolumnom w tabeli nale y umie ciü atrybut Column (z tej sa- mej przestrzeni nazw), w którym mo emy wskazaü m.in. nazw kolumny w tabeli (pa- rametr Name), poinformowaü go, czy jest kluczem gáównym (IsPrimaryKey) lub czy mo e przyjmowaü puste warto ci (CanBeNull). Listing 3.1 zawiera przykáad klasy encji, w której definiujemy typ rekordu z tabeli ListaOsob z bazy danych Telefony.mdf zna- nej z poprzedniego rozdziaáu.2 Listing 3.1. Klasa encji zwi zana z tabel ListaOsob z bazy Telefony.mdf [Table(Name = "ListaOsob")] public class Osoba { [Column(Name = "Id", IsPrimaryKey = true)] public int Id; [Column(Name = "Imiú", CanBeNull = false)] public string Imiú; [Column(Name = "Nazwisko", CanBeNull = false)] public string Nazwisko; [Column] public int NumerTelefonu; [Column] public int Wiek; } W powy szym listingu wi zanie klasy ze struktur bazy danych przeprowadzane zo- staje na podstawie atrybutów doá czanych do definicji klasy. W terminologii Microsoft nazywane jest to mapowaniem opartym na atrybutach (ang. attribute-based mapping). 1 Klasy z przestrzeni nazw System.Data.Linq i jej podprzestrzeni, m.in. z System.Data.Linq.Mapping, do której nale y klasa Table, zdefiniowane s w osobnej bibliotece System.Data.Linq.dll, nale cej do zbioru bibliotek platformy .NET 3.5. Domy lnie nie jest ona wá czana do zbioru bibliotek projektu. Nale y j zatem dodaü samodzielnie, korzystaj c z polecenia Project, Add Reference…. Omówione ni ej narz dzie wizualnego projektowania klas encji zwolni nas z tego obowi zku. 2 Tworz c tabel w bazie SQL Server mogli my zezwoliü, aby niektóre jej pola dopuszczaáy pust warto ü. Definiuj c klas encji warto zadeklarowaü odpowiadaj ce im pola klasy w taki sposób, aby dopuszczaáy przypisanie warto ci null. W przypadku áa cuchów nie ma problemu – typ String jest typem referencyjnym i zawsze mo na mu przypisaü warto ü null. Inaczej wygl da to np. w przypadku typu int, który jest typem warto ciowym. Nale y wówczas w deklaracji pola wykorzystaü typ parametryczny Nullable<int>.
  • 6. Rozdziaä 3. i LINQ i SQL Server 31 Mo liwe jest równie podej cie alternatywne, w którym mapowanie odbywa si na podstawie struktury zapisanej w pliku XML. Takie podej cie nosi nazw mapowania zewn trznego i nie b d si nim tu zajmowaá. Po jego opis warto zajrzeü na stron MSDN: http://msdn2.microsoft.com/en-us/library/bb386907.aspx. LINQ to SQL daje dobry pretekst do wspomnienia o zagadnieniu modelowania da- nych. Jest to ciekawa gaäñ informatyki, ale nie chciaäbym snuè dygresji na jej temat. Osoby zainteresowane teoriñ przechowywania danych powinny w Google wpisaè hasäo data modeling lub modelowanie danych. Jak wspomniaáem wcze niej, klasa encji zwykle nie jest tworzona r cznie. Zwykle do jej projektowania wykorzystywany jest edytor O/R Designer, który omówi w dalszej cz ci tego rozdziaáu. Wydaje mi si jednak, e przy pierwszych próbach korzystania z technologii LINQ to SQL warto zrobiü wszystko samodzielnie. Dotyczy to równie powoáywania instancji klasy DataContext, czym zajmiemy si ju za chwil . Pobieranie danych Zacznijmy od zdefiniowania pól przechowuj cych referencje do instancji klasy Data ´Context i jej tabeli ListaOsob: static string nazwaPliku = "Telefony.mdf"; static DataContext bazaDanychTelefony = ´new DataContext(System.IO.Path.GetFullPath(nazwaPliku)); static Table<Osoba> listaOsob = bazaDanychTelefony.GetTable<Osoba>(); Tworzymy obiekt DataContext i pobieramy z niego referencj do tabeli (klasa Table parametryzowana klas encji Osoba). Klasa DataContext znajduje si w przestrzeni nazw System.Data.Linq, nale y wi c uwzgl dniü j w grupie polece using3. Ostat- nia instrukcja tworzy pole o nazwie listaOsob typu Table parametryzowanego nasz klas encji Osoba. Referencja ta b dzie umo liwiaü dost p do danych pobranych z tabeli ListaOsob. Nazwa pobieranej tabeli wskazana zostaáa w atrybucie Table, którym poprze- dzili my klas encji. Dlatego jej nazwa nie pojawia si w powy szych definicjach. Obiekt klasy DataContext reprezentuje baz danych. Z kolei klasa encji zdefiniowana w listingu 3.1 dostarcza informacji o strukturze konkretnej tabeli (encji). Dzi ki obu klasom mo emy poá czyü si z baz danych i pobraü dane z interesuj cej nas tabeli. Prezentuje to listing 3.2. Listing 3.2. Pobieranie danych z tabeli w bazie SQL Server za pomoc LINQ to SQL private void button1_Click(object sender, EventArgs e) { //pobieranie kolekcji var listaOsobPelnoletnich = from osoba in listaOsob 3 Tu stosuje si równie uwaga z poprzedniego przypisu. Ponadto konstruktor klasy DataContext wymaga, aby cie ka do pliku podana w argumencie byáa bezwzgl dna (ang. full path).
  • 7. 32 C# 3.0 i .NET 3.5. Technologia LINQ where osoba.Wiek>=18 select osoba; //wy wietlanie pobranej kolekcji string s = "Lista osób pe noletnich:n"; foreach (Osoba osoba in listaOsobPelnoletnich) s+=osoba.Imiú+" "+osoba.Nazwisko ´+" ("+osoba.Wiek+")n"; MessageBox.Show(s); } W zapytaniu LINQ (pierwsza instrukcja metody widocznej w listingu 3.2) pobiera z ta- beli list osób, które maj co najmniej 18 lat. Zwróümy uwag na podobie stwo tego zapytania do tego, które stosowali my w przypadku LINQ to Objects w pierwszym roz- dziale. W listingu 3.2 klasa encji Osoba pojawia si tylko raz w p tli foreach. Co wi cej, skoro jest jasne, e ka dy rekord jest obiektem typu Osoba, a to wiadomo dzi ki parametry- zacji pola listaOsob, jawne wskazanie typu w tej p tli nie jest konieczne i z równym skutkiem mogliby my u yü sáowa kluczowego var — kompilator sam wywnioskowaáby, z jakim typem ma do czynienia. Aktualizacja danych w bazie Pobieranie danych, wizytówka LINQ, to zwykle pierwsza czynno ü wykonywana przez aplikacje. Technologia LINQ to SQL nie poprzestaje tylko na tym. Zmiany wprowa- dzone w pobranej zapytaniem LINQ kolekcji mo na w áatwy sposób przesáaü z powro- tem do bazy danych. Sáu y do tego metoda SubmitChanges obiektu DataContext. Tym samym wszelkie modyfikacje danych staj si bardzo naturalne: nie ma konieczno ci przygotowywania polece SQL, odpowiedzialnych za aktualizacj tabel w bazie da- nych — wszystkie operacje wykonujemy na obiektach C#. Zachowana jest w ten spo- sób spójno ü programu, co pozwala na kontrol typów i peán weryfikacj kodu ju w trakcie kompilacji. Modyfikacje istniejñcych rekordów Poka my to na prostym przykáadzie. Zaáó my, e mija Nowy Rok i z tej okazji zwi k- szamy warto ü w polach Wiek wszystkich osób. Rzecz jasna wszystkich, poza kobie- tami, które s ju peánoletnie. Pobieramy zatem kolekcj osób, które s m czyznami lub s niepeánoletnie. Spójnik „lub” u yty w poprzednim zdaniu rozumiany powinien byü tak, jak zdefiniowany jest operator logiczny OR — powinni my uzyskaü sum mno- go ciow zbiorów osób niepeánoletnich i zbioru m czyzn. Nast pnie zwi kszamy war- to ü pola Wiek ka dej z osób tak uzyskanego zbioru. I najmilsza rzecz: aby zapisaü nowe warto ci do pliku bazy danych, wystarczy tylko wywoáaü metod SubmitChanges na rzecz obiektu bazaDanychTelefony. Powy sze czynno ci uj te w j zyku C# prezentuje listing 3.3.
  • 8. Rozdziaä 3. i LINQ i SQL Server 33 Listing 3.3. Modyfikowanie istniej cego rekordu private void button2_Click(object sender, EventArgs e) { //pobieranie kolekcji var listaOsobDoZmianyWieku = from osoba in listaOsob where (osoba.Wiek<18 || !osoba.Imiú.EndsWith("a")) select osoba; //wy wietlanie pobranej kolekcji string s = " Lista osób niebúdæcych pe noletnimi kobietami:n"; foreach (Osoba osoba in listaOsobDoZmianyWieku) s += osoba.Imiú + " " + ´osoba.Nazwisko + " (" + osoba.Wiek + ")n"; MessageBox.Show(s); //modyfikowanie kolekcji foreach (Osoba osoba in listaOsobDoZmianyWieku) osoba.Wiek++; //wy wietlanie peánej listy osób kolekcji po zmianie s = "Lista wszystkich osób:n"; foreach (Osoba osoba in listaOsob) s += osoba.Imiú + " " + osoba.Nazwisko + " (" ´+ osoba.Wiek + ")n"; MessageBox.Show(s); //zapisywanie zmian bazaDanychTelefony.SubmitChanges(); } Musi pojawiü si pytanie, sk d obiekt bazaDanychTelefony (obiekt typu DataContext reprezentuj cy w naszej aplikacji baz danych) wie o modyfikacjach wprowadzonych do kolekcji listaOsobDoZmianyWieku otrzymanej zapytaniem LINQ z kolekcji uzyskanej metod bazaDanychTelefony.GetTable<Osoba>(). Otó st d, e kolekcja listaOsobDo ´ZmianyWieku przechowuje tylko referencje do obiektów tej tabeli, a nie kopie tych obiektów (por. zapytania LINQ w podrozdziale „Mo liwo ü modyfikacji danych ró- dáa”, w rozdziale pierwszym). Zreszt w przypadku LINQ to SQL próba uruchomienia zapytania, w którym tworzymy kopie obiektów, sko czy si zgáoszeniem wyj tku NotSupportedException. Tak wi c wszystkie zmiany wprowadzane do kolekcji wpro- wadzane s automatycznie w buforze obiektu bazaDanychTelefony, przechowuj cym dane pobrane z bazy danych. A obiekt ten ju potrafi zapisaü je z powrotem do tabeli SQL Server. Warto przy tym pami taü, e wszystkie zmiany wprowadzane w kolekcji s przechowywane tylko w niej a do momentu wywoáania metody SubmitChanges. Mo- emy wi c dowolnie (wielokrotnie) modyfikowaü kolekcj bez obawy, e nadu ywamy zasobów bazy danych i komputera, zmniejszaj c wydajno ü programu. W trakcie projektowania aplikacji nale y zwróciè uwagö, czy plik bazy danych widoczny w podoknie Solution Explorer jest kopiowany do katalogu, w którym umieszczana jest skompilowana aplikacja (podkatalog bin/Debug lub bin/Release). Mo e to wprowadzaè pewne zamieszanie i utrudniaè ledzenie zmian w bazie danych np. za pomocñ podokna Database Explorer.
  • 9. 34 C# 3.0 i .NET 3.5. Technologia LINQ Dodawanie i usuwanie rekordów Co jeszcze mo emy zmieniü w tabeli? W zasadzie pozostaje tylko dodawanie nowych i usuwanie istniej cych rekordów. Równie to zadanie jest dzi ki LINQ to SQL bardzo proste. W tym przypadku zmiany musz byü jednak wprowadzane wprost w obiekcie reprezentuj cym tabel — instancji klasy DataContext, a nie w pobranej z niego ko- lekcji. Listing 3.4 pokazuje, jak dodaü do tabeli nowy rekord. Po utworzeniu obiektu DataContext (polecenia identyczne jak w poprzednich listingach) obliczamy warto ü pola Id dla nowego rekordu — do najwi kszej warto ci Id w tabeli dodajemy jeden4 — korzystamy przy tym z rozszerzenia Max. Nast pnie tworzymy obiekt typu Osoba i poleceniem InsertOnSubmit dodajemy go do tabeli. Rzeczywista zmiana nast pi w momencie najbli szego wywoáania metody SubmitChanges obiektu DataContext. Listing 3.4. Dodawanie rekordu do tabeli private void button3_Click(object sender, EventArgs e) { //dodawanie osoby do tabeli int noweId = listaOsob.Max(osoba => osoba.Id) + 1; MessageBox.Show("Nowe Id: " + noweId); Osoba noworodek = new Osoba { Id = noweId, Imiú = "Nela", Nazwisko = ´"Matulewska", NumerTelefonu = 0, Wiek = 0 }; listaOsob.InsertOnSubmit(noworodek); //zapisywanie zmian bazaDanychTelefony.SubmitChanges(); //dodawany jest tak e nowy rekord //wy wietlanie tabeli string s = "Lista osób:n"; foreach (Osoba osoba in listaOsob) s += osoba.Imiú + " " + osoba.Nazwisko + " (" ´+ osoba.Wiek + ")n"; MessageBox.Show(s); } Równie áatwo usun ü z tabeli rekord lub ich grup . Nale y tylko zdobyü referencj do odpowiadaj cego im obiektu (wzgl dnie grupy obiektów). W przypadku pojedyncze- go rekordu nale y u yü metody DeleteOnSubmit, w przypadku ich kolekcji — Delete ´AllOnSubmit. W obu przypadkach rekordy zostan oznaczone jako przeznaczone do usuni cia i rzeczywi cie usuni te z bazy danych przy najbli szym wywoáaniu metody SubmitChanges. Listing 3.5 prezentuje metod usuwaj c z tabeli wszystkie osoby o imieniu Nela. Listing 3.5. Wszystkie modyfikacje w bazie danych wykonywane s w momencie wywoáania metody SubmitChanges private void button4_Click(object sender, EventArgs e) { //wybieranie elementów do usuni cia i ich oznaczanie IEnumerable<Osoba> doSkasowania = from osoba in listaOsob 4 Wáa ciwsze byáoby pewnie wyszukanie najmniejszej wolnej warto ci, ale nie chciaáem niepotrzebnie komplikowaü kodu. Zreszt zwykle tak post puj , w my l zasady „prosty kod oznacza mniejsze ryzyko bá du”.
  • 10. Rozdziaä 3. i LINQ i SQL Server 35 where osoba.Imiú == "Nela" select osoba; listaOsob.DeleteAllOnSubmit(doSkasowania); //zapisywanie zmian bazaDanychTelefony.SubmitChanges(); //wy wietlanie tabeli string s = "Lista osób:n"; foreach (Osoba osoba in listaOsob) s += osoba.Imiú + " " + osoba.Nazwisko + " (" ´+ osoba.Wiek + ")n"; MessageBox.Show(s); } Klasa DataContext säu y nie tylko do pobierania i modyfikacji zawarto ci bazy danych. Za pomocñ jej metod CreateDatabase i DeleteDatabase mo na tak e tworzyè i usu- waè bazy danych SQL Server z poziomu kodu. Za pomocñ metody ExecuteCommand mo na wykonaè podane w argumencie polecenie SQL, a za pomocñ ExecuteQuery — uruchomiè zapytanie SQL i odczytaè pobrane przez nie dane. Wizualne projektowanie klasy encji W przypadku bardziej rozbudowanych baz danych najpro ciej klas encji utworzyü, korzystaj c z wbudowanego w Visual Studio narz dzia, którego nazwa w dosáownym táumaczeniu to „projektant obiektowo-relacyjny” (ang. Object Relational Designer, w skrócie: O/R Designer) i który w istocie umo liwia automatyczne mapowanie struk- tury tabeli bazy danych w klasach C#. Nie chciaáem od niego rozpoczynaü omawiania LINQ to SQL, aby daü Czytelnikowi mo liwo ü poznania technologii „od podszewki”, tj. od wáasnor cznie przygotowanej klasy encji. Ale skoro ju tak klas sami przy- gotowali my, nie musimy tego wi cej powtarzaü. Co prawda samodzielnie przygoto- wane klasy encji s zwykle bardziej zwarte, ale pisz c je, mo emy popeániaü bá dy, których unikniemy, tworz c klasy myszk . O/R Designer Zacznijmy od utworzenia klasy encji dla tabeli ListaOsob w bazie Telefony.mdf. W tym celu z menu Project wybieramy polecenie Add New Item. Pojawi si okno widoczne na rysunku 3.1. Zaznaczamy w nim ikon LINQ to SQL Classes. W polu Name poda- jemy nazw nowego pliku: Telefomy.dbml. Po zamkni ciu okna dialogowego zoba- czymy now zakáadk . Na razie pust , nie licz c napisów informuj cych, e na dwa widoczne na niej panele nale y przenosiü elementy z podokna Database Explorer. Przenie my na lewy panel tabel ListaOsob (rysunek 3.2). Konwencja nazw w pliku Telefony.dbml nie przystaje niestety do nazw, jakich u yáem w bazie Telefony.mdf. Auto- matycznie tworzona klasa encji przejmuje bowiem nazw tabeli, tj. ListaOsob (nasza r cznie przygotowana klasa encji nazywaáa si Osoba). Z kolei wáasno ü tylko do od- czytu zdefiniowana w klasie TelefonyDataContext, która zwraca tabel (a konkretnie
  • 11. 36 C# 3.0 i .NET 3.5. Technologia LINQ Rysunek 3.1. Tworzenie klasy reprezentuj cej dane Rysunek 3.2. Zakáadka z O/R Designer kolekcj typu Table<ListaOsob>), nazywa si ListaOsobs z „s” dodanym na ko cu. Gdyby tabela nazywaáa si np. Person, klasa encji nazywaáaby si Person, a wáasno ü reprezentuj ca tabel — Persons. Wówczas nazwy brzmiaáyby du o lepiej. A tak mamy ListaOsobs.
  • 12. Rozdziaä 3. i LINQ i SQL Server 37 Co prawda nazwy utworzonych przez O/R Designera klas mo na áatwo zmieniü — wy- starczy na zakáadce Telefony.dbml klikn ü nagáówek tabeli (rysunek 3.2) i wpisaü nowe nazwy. To samo dotyczy nazw pól domy lnie ustalonych na identyczne jak znalezione w tabeli SQL Server. Je eli wpiszemy nazw ró n od tej w tabeli, O/R Designer zmo- dyfikuje atrybut Column, który wska e pole tabeli, z jakim definiowane pole obiektu ma byü zwi zane. Utworzona przez O/R Designer klasa ListaOsob (mo na j znale ü w pliku Telefony. ´designer.cs) jest klas encji o identycznej funkcji jak zdefiniowana przez nas wcze niej klasa Osoba. Nie jest jednak z ni identyczna. T pierwsz O/R Designer wyposa yá poza polami, które i my zdefiniowali my, równie w zbiór metod i zdarze . Zawiaduje nimi O/R Designer i poza wyj tkowymi sytuacjami raczej nie nale y edytowaü ich kodu. Same pola, inaczej ni w naszej prostej implementacji, s w nowej klasie prywatne i poprzedzone znakiem podkre lenia. Zwróümy uwag , e te z nich, które odpowiadaj tym polom tabeli, które dopuszczaj pust warto ü, zdefiniowane zostaáy przy u yciu typu parametrycznego System.Nullable<typ>, gdzie typ to oryginalny typ danych .NET (w naszym przypadku int lub string). Dost p do tych pól mo liwy jest poprzez pu- bliczne wáasno ci. Przykáad takiej wáasno ci odpowiadaj cej polu Id widoczny jest na listingu 3.6. Wáasno ü poprzedzona jest atrybutem Column, którego u ywali my te w naszej wcze niejszej klasie encji. Jej argumenty s jednak inne (poza IsPrimaryKey ustawionym na true). Ze wzgl du na identyczn nazw pola tabeli i wáasno ci klasy argument Name zostaá tu pomini ty. Dwa nowe argumenty to Storage, który wskazuje prywatne pole przechowuj ce warto ü komórki, oraz DbType. W tym ostatnim przecho- wywana jest informacja o oryginalnym typie pola tabeli (kolumny). Tworzy go nazwa typu dozwolona przez SQL Server (np. Int lub NVarChar(MAX)), uzupeániona ewentu- alnie fraz NOT NULL, je eli baza nie dopuszcza pustych warto ci dla tego pola. Listing 3.6. Wáasno ü Id klasy ListaOsob. Towarzyszy jej pole zdefiniowane jako private int _Id [Column(Storage="_Id", DbType="Int NOT NULL", IsPrimaryKey=true)] public int Id { get { return this._Id; } set { if ((this._Id != value)) { this.OnIdChanging(value); this.SendPropertyChanging(); this._Id = value; this.SendPropertyChanged("Id"); this.OnIdChanged(); } }
  • 13. 38 C# 3.0 i .NET 3.5. Technologia LINQ Wspomniana klasa reprezentuj ca caá baz danych zawiera wáasno ci odpowiadaj ce tabelom bazy. Jest zatem, to modne ostatnio okre lenie, strongly typed. Pozwala dzi ki temu na bezpieczny, tj. zachowuj cy typy danych, dost p do zewn trznego zasobu — do danych w bazie SQL Server. Nowe klasy TelefonyDataContext i ListaOsob mo na wykorzystaü tak, jak robili my do tej pory z klas Osoba i „r cznie” tworzon instancj klasy DataContext. Listing 3.7 pokazuje kod metody, w której zmiany dotycz w zasadzie wyá cznie nazw klas: z wcze- niej u ywanych DataContext i Osoba na TelefonyDataContext i ListaOsob. Skorzy- staáem tak e z wáasno ci ListaOsobs (z „s” na ko cu) pierwszej z klas, aby pobraü re- ferencj do kolekcji zawieraj cej dane z tabeli ListaOsob (wyró nienie w listingu 3.7). Listing 3.7. Korzystanie z automatycznie utworzonej klasy encji do pobierania i modyfikacji danych z tabeli SQL Server private void button5_Click(object sender, EventArgs e) { //tworzenie obiektu DataContext i pobieranie danych z tabeli string nazwaPliku = "Telefony.mdf"; nazwaPliku = Path.GetFullPath(nazwaPliku); if (!File.Exists(nazwaPliku)) { MessageBox.Show("Brak pliku " + nazwaPliku); return; } TelefonyDataContext bazaDanychTelefony = new TelefonyDataContext(nazwaPliku); var listaOsob = bazaDanychTelefony.ListaOsobs; //pobieranie kolekcji var listaOsobPelnoletnich=from osoba in listaOsob where osoba.Wiek>=18 select osoba; //wy wietlanie pobranej kolekcji string s = "Lista osób pe noletnich:n"; foreach (ListaOsob osoba in listaOsobPelnoletnich) s += osoba.Imiú + " " + osoba.Nazwisko + " (" + osoba.Wiek + ")n"; MessageBox.Show(s); //informacje o pobranych danych MessageBox.Show("Typ: " + listaOsobPelnoletnich.GetType().FullName); MessageBox.Show("Ilo è pobranych rekordów: " + ´listaOsobPelnoletnich.Count().ToString()); MessageBox.Show("Suma wieku wybranych osób: " ´+ listaOsobPelnoletnich.Sum(osoba => osoba.Wiek).ToString()); MessageBox.Show("Imiú pierwszej osoby: " + listaOsobPelnoletnich.First().Imiú); s = "Pe na lista osób:n"; foreach (ListaOsob osoba in listaOsob) s += osoba.Imiú + " " + osoba.Nazwisko + " (" + osoba.Wiek + ")n"; MessageBox.Show(s); }
  • 14. Rozdziaä 3. i LINQ i SQL Server 39 Wspóäpraca z kontrolkami tworzñcymi interfejs aplikacji Ewidentnie nadu ywam metody MessageBox.Show. Bardziej naturalne do prezentacji danych jest oczywi cie korzystanie z kontrolek, np. DataGridView. Bez trudu mo na taki komponent wypeániü danymi udost pnianymi przez klas TelefonyDataContext. Dodajmy do projektu now form i zdefiniujmy w niej pole — instancj tej ostatniej klasy: TelefonyDataContext bazaDanychTelefony = new TelefonyDataContext(); Nast pnie wystarczy umie ciü na formie kontrolk DataGridView i przypisaü jej wáa- sno ci DataSource odpowiedni tabel (np. w konstruktorze za poleceniem Initialize ´Component();): dataGridView1.DataSource = bazaDanychTelefony.ListaOsobs; Je eli nie chcemy prezentowaü peánej zawarto ci tabeli, wáasno ci DataSource mo emy przypisaü kolekcj zwracan przez zapytanie LINQ: dataGridView1.DataSource = from osoba in bazaDanychTelefony.ListaOsobs where osoba.Wiek >= 18 orderby osoba.Imiú select new { osoba.Imiú, osoba.Nazwisko, osoba.Wiek }; Kontrolka DataGridView pozwala na edycj danych z kolekcji, jednak pod warunkiem, e prezentowana w niej kolekcja nie jest zbudowana z obiektów anonimowych typów, lecz z referencji do obiektów ze ródáa danych (instancji klas encji): dataGridView1.DataSource = from osoba in bazaDanychTelefony.ListaOsobs where osoba.Wiek >= 18 orderby osoba.Imiú select osoba; Aby wprowadzone w ten sposób modyfikacje danych wysáaü z powrotem do bazy, nale y tylko wywoáaü metod SubmitChanges instancji klasy TelefonyDataContext, tj. obiektu bazaDanychTelefony. Do formy mo emy dodaü tak e rozwijan list ComboBox. Mo emy „podá czyü” j do tego samego wi zania, którym z baz poá czona jest kontrolka dataGridView1. W tym celu do konstruktora nale y dopisaü dwa polecenia: comboBox1.DataSource = dataGridView1.DataSource; comboBox1.DisplayMember = "Imiú"; Pierwsze wskazuje na ródáo danych rozwijanej listy — jest nim ta sam kolekcja, która prezentowana jest w kontrolce dataGridView1. Drugie precyzuje, któr kolumn da- nych rozwijana lista ma prezentowaü. Ze wzgl du na korzystanie ze wspólnego wi - zania zmiana aktywnego rekordu w siatce spowoduje zmian rekordu w rozwijanej li- cie i odwrotnie.
  • 15. 40 C# 3.0 i .NET 3.5. Technologia LINQ Kreator ródäa danych i automatyczne tworzenie interfejsu u ytkownika Do utworzenia odpowiednich obiektów mo na jednak ponownie zaprz c Visual C#. Oczy- wi cie, w takim przypadku kod nie b dzie tak prosty i przejrzysty jak ten napisany sa- modzielnie, ale za to nie musimy go przygotowywaü i sprawdzaü sami. Cel, do którego d ymy, to utworzenie ródáa danych, takiego, do jakich przyzwyczaiáo nas ADO.NET. Jednak w tym przypadku czerpaü ono b dzie dane nie bezpo rednio z bazy danych, ale za pomoc LINQ to SQL, a wi c poprzez zaprojektowan w O/R Designerze klas TelefonyDataContext i towarzysz c jej klas encji. Dysponuj c takim ródáem, b - dziemy mogli wi zaü z danymi kontrolki, z których budujemy interfejs aplikacji. Wybierzmy z menu Data polecenie Add New Data Source…. Pojawi si kreator Data Source Configuration Wizard. W jego pierwszym kroku wybieramy ródáo danych (rysu- nek 3.3, górny); zaznaczmy ikon Object. Klikamy Next >. W nast pnym kroku wy- bieramy klas , która zawiera informacje na temat struktury tabeli ListaOsob (rysunek 3.3, dolny). W naszym przypadku jest to klasa ListaOsob. Wreszcie klikamy Finish. Po zamkni ciu kreatora wybierzmy polecenie Show Data Sources z menu Data. Pojawi si nowe podokno o nazwie Data Sources, w którym zobaczymy nowe, utworzone przed chwil ródáo danych. Mo emy sprawdziü jego pola — powinny odpowiadaü polom tabeli (rysunek 3.4). Tak zdefiniowane ródáo danych nie zawiera niestety samych da- nych, a jedynie informacje o ich strukturze. To jednak wystarczy, aby bardzo przyspie- szyü projektowanie interfejsu u ytkownika w aplikacjach bazodanowych. Gdy dysponujemy ródáem danych, mo emy zaprojektowaü interfejs aplikacji, korzy- staj c z metody „przeci gnij i upu ü”. Mo emy bowiem przeci gaü na form poszcze- gólne pola tabeli ListaOsob widoczne w podoknie Data Sources. Powstanie wówczas kontrolka z automatycznie dodanym opisem. Typ kontrolki, która powstanie, mo na wcze niej wybraü w rozwijanych listach zwi zanych z ka dym polem, w podoknie Data Sources (rysunek 3.4). Przeniesienie caáej tabeli spowoduje przy domy lnych usta- wieniach umieszczenie na formie siatki dataGridView. Jednak je eli wcze niej w pozycji ListaOsob (w podoknie Data Sources) z rozwijanej listy wybierzemy Details zamiast domy lnego DataGridView, zamiast siatki na formie umieszczony zostanie zbiór kon- trolek zgodnie z wyborem dla ka dego z pól. Wraz z pierwsz umieszczon w ten sposób kontrolk na formie pojawi si komponent wi zania (listaOsobBindingSource) oraz kontrolka nawigacyjna (listaOsobBindingNavigator). T ostatni mo emy zoba- czyü na szczycie podgl du formy na rysunku 3.4. Tak jak uprzedzaáem, ródáo danych nie zawiera danych, a jedynie informacje o ich strukturze. Zatem po skompilowaniu kontrolki nie b d prezentowaáy adnych sen- sownych informacji. Wystarczy jednak odpowiednio „podpi ü” kontrolk wi zania listaOsobBindingSource, aby wszystko zacz áo graü. Zaczynamy od zdefiniowania pola formy b d cego instancj naszej klasy reprezentuj cej baz danych: TelefonyDataContext bazaDanychTelefony = new TelefonyDataContext();
  • 16. Rozdziaä 3. i LINQ i SQL Server 41 Rysunek 3.3. Pierwszy krok kreatora obiektu — ródáa danych LINQ to SQL Nast pnie w konstruktorze wi emy udost pnian przez ten obiekt tabel ListaOsob z obiektem wi zania listaOsobBindingSource: listaOsobBindingSource.DataSource = bazaDanychTelefony.ListaOsobs;
  • 17. 42 C# 3.0 i .NET 3.5. Technologia LINQ Rysunek 3.4. Projektowanie interfejsu aplikacji na bazie ródáa danych LINQ Wszystkie wizualne kontrolki tworz ce interfejs u ytkownika zwi zane s z tym jed- nym obiektem wi zania, zatem zmiana aktualnego rekordu w którejkolwiek z nich spo- woduje automatyczn zmian widocznego rekordu w pozostaáych. Mo liwe jest oczy- wi cie zapisywanie zmian wprowadzonych za pomoc kontrolek. Wystarczy jedynie wywoáaü metod bazaDanychTelefony.SubmitChanges. ãñczenie danych z dwóch tabel — operator join Informacje o osobach mog byü umieszczone w kilku tabelach. Dla przykáadu w osob- nej tabeli mógáby byü umieszczony spis rozmów, jakie przeprowadzaáy osoby z tabeli ListaOsob. Tabela b dzie zawieraü identyfikator osoby, personalia jej rozmówcy, dat prze- prowadzenia rozmowy i jej czas trwania w minutach. Pola o nazwie Id i CzasTrwania b d typu int, pole Rozmowca — typu nvarchar(MAX), a pole Data — typu datetime. adne z pól nie b dzie dopuszczaü pustych warto ci. Kluczem gáównym mo emy uczyniü tylko pole Data. Zapiszmy tabel , nazywaj c j po prostu Rozmowy. Pole Id w nowej tabeli b dzie tym samym Id, którym identyfikowana jest osoba w tabeli ListaOsob. Zatem ka dej osobie b dzie mo na przyporz dkowaü list rozmów, a ka dej rozmowie — tylko jednego rozmówc . Tabela ListaOsob b dzie wi c nasz tabel -rodzicem, a ta- bela Rozmowy — tabel -dzieckiem. Tabel nale y oczywi cie wypeániü jakimi przy- káadowymi danymi (rysunek 3.5). Nast pnie przejd my na zakáadk Telefony.dbml i przenie my now tabel na lewy panel, obok tabeli ListaOsob. Do klasy TelefonyDataContext dodana zostanie nowa wáasno ü o nazwie Rozmowies (znowu nie dopasowali my si do proangielskiego schematu nazw). Pobierzmy teraz list rozmów trwaj cych dáu ej ni dziesi ü minut wraz z persona- liami dzwoni cej osoby. W tym celu zapytanie LINQ rozszerzymy o operator join, który pobieraü b dzie rekordy o tych samych warto ciach pól Id w obu tabelach. Po- kazuje to listing 3.8.
  • 18. Rozdziaä 3. i LINQ i SQL Server 43 Rysunek 3.5. Nowa tabela bazy Telefony.mdf Listing 3.8. Pomin áem polecenia tworz ce obiekt bazaDanychTelefony var listaOsob = bazaDanychTelefony.ListaOsobs; var rozmowy = bazaDanychTelefony.Rozmowies; IEnumerable<string> listaDlugichRozmow = from osoba in listaOsob join rozmowa in rozmowy on osoba.Id equals rozmowa.Id where rozmowa.CzasTrwania > 10 select osoba.Imiú + " " + osoba.Nazwisko + ", " + rozmowa.Data.ToString() ´+" (" + rozmowa.CzasTrwania + ")"; string s = "Lista rozmów trwajæcych d u ej ni 10 min:n"; foreach (string opis in listaDlugichRozmow) s += opis + "n"; MessageBox.Show(s); Relacje (Associations) Zamiast korzystaü z operatora join, mo emy poá czyü obie tabele w O/R Designerze. A w zasadzie nie tabele, tylko reprezentuj ce je klasy. Przejd my na zakáadk Telefony. ´dbml, kliknijmy prawym przyciskiem myszy nagáówek tabeli ListaOsob i z kontek- stowego menu wybierzmy polecenie Add, Association. Pojawi si edytor relacji (ry- sunek 3.6). Z rozwijanej listy Child Class wybieramy Rozmowy. Nast pnie w tabeli Association Properties pod spodem wybieramy w obu kolumnach pole Id.
  • 19. 44 C# 3.0 i .NET 3.5. Technologia LINQ Rysunek 3.6. Edytor poá czenia mi dzy obiektami reprezentuj cymi tabele Ustanowione poá czenie zaznaczone zostanie w O/R Designerze strzaák á cz c dwie tabele. W podobny sposób zaznaczone byáyby relacje mi dzy tabelami, które zdefi- niowane s w samej bazie danych. Skutek obu poá cze jest podobny. Dzi ki relacji á cz cej obie tabele mo emy upro ciü zapytanie LINQ: var listaDlugichRozmow = from rozmowa in rozmowy where rozmowa.CzasTrwania > 10 select rozmowa.ListaOsob.Imiú + " " + ´rozmowa.ListaOsob.Nazwisko + ", " + ´rozmowa.Data.ToString() + ´" (" + rozmowa.CzasTrwania + ")"; ; Jest to mo liwe, poniewa do klasy encji Rozmowy dodana zostaáa wáasno ü ListaOsob, która wskazuje na jeden pasuj cy rekord tabeli ListaOsob. Z kolei klasa encji ListaOsob zawiera wáasno ü Rozmowies obejmuj c peáen zbiór rekordów, w których warto ü pola Id równa jest tej, jaka jest w bie cym wierszu tabeli ListaOsob. To ostatnie pozwala na proste filtrowanie danych bez konieczno ci przygotowywania zapytania LINQ. A wi c kolekcja uzyskana poleceniem: var listaRozmowKarolinyMatulewskiej = ´bazaDanychTelefony.ListaOsobs.Single(osoba => osoba.Id == 3).Rozmowies; zawiera identyczne rekordy jak uzyskana zapytaniem: var listaRozmowKarolinyMatulewskiej = from rozmowa in rozmowy where rozmowa.Id == 3 select rozmowa; Korzystanie z procedur skäadowanych W momencie uruchamiania metody SubmitChanges obiekt klasy DataContext automa- tycznie tworzy zbiór polece SQL, które modyfikuj zawarto ü bazy danych. Podob- nie jest zreszt w momencie pobierania danych. Wówczas zapytanie LINQ jest táuma- czone na zapytanie SQL i wysyáane do bazy danych.
  • 20. Rozdziaä 3. i LINQ i SQL Server 45 Zamiast korzystaü z tych tworzonych automatycznie procedur i zapyta mo emy wy- korzystaü wáasne procedury skáadowane w bazie danych (ang. stored procedures). Jest to w pewnym sensie krok wstecz, wymaga bowiem programowania w SQL, ale za to po- zwala na zachowanie peánej elastyczno ci podczas korzystania z SQL Server. I nawet je eli z procedur skáadowych nie b dziemy korzystaü do pobierania danych, warto je poznaü, aby móc uruchamiaü dowolne polecenia SQL, które pozwol nam np. tworzyü nowe tabele w bazie. Pobieranie danych za pomocñ procedur skäadowanych Utwórzmy i zapiszmy w bazie danych zapytanie pobieraj ce personalia osób peánoletnich zapisanych w tabeli ListaOsob. W tym celu otwórzmy plik Telefony.mdf w Database Explorer, przejd my do pozycji Stored Procedures i prawym przyciskiem myszy roz- wi my jej menu kontekstowe. Wybierzmy z niego polecenie Add New Stored Procedure. Pojawi si edytor, w którym mo emy wpisaü kod SQL (rysunek 3.7). Za sáowem kluczo- wym AS wpiszmy proste zapytanie SQL: SELECT * FROM ListaOsob WHERE Wiek>=18. Zmie my te nazw procedury na dbo.ListaOsobPelnoletnich. Wreszcie zapiszmy zmiany w bazie danych (Ctrl+S). W podoknie Database Explorer, w gaá zi Stored Procedures bazy Telefony.mdf, powinna pojawiü si pozycja ListaOsobPelnoletnich. Mo emy wów- czas przej ü na zakáadk Telefony.dbml i przeci gn ü procedur z podokna Database Explorer do pustego panelu po prawej stronie. To spowoduje dodanie do klasy Telefony ´DataContext metody ListaOsobPelnoletnich. Zwraca ona dane pobrane przez za- pytanie SQL w postaci kolekcji elementów typu ListaOsobPelnoletnichResult. Rysunek 3.7. Edycja zapytania SQL procedury umieszczonej w bazie danych Typ ListaOsobPelnoletnichResult zostaá automatycznie utworzony za pomoc O/R Designera. W przypadku pobierania wszystkich pól z tabeli, tj. gdy w zapytaniu SQL po sáowie SELECT widoczna jest gwiazdka (*), nowa klasa b dzie równowa na typowi ListaOsob (i Osoba). Zapytanie SQL mo e jednak zwracaü tylko wybrane pola, a wów- czas tworzenie nowego typu jest bardziej przydatne.
  • 21. 46 C# 3.0 i .NET 3.5. Technologia LINQ Dzi ki nowej metodzie uruchomienie skáadowanego zapytania SQL i odebranie zwra- canych przez nie danych jest dziecinnie proste: IEnumerable<ListaOsobPelnoletnichResult> listaOsobPelnoletnich = ´bazaDanychTelefony.ListaOsobPelnoletnich(); Modyfikowanie danych za pomocñ procedur skäadowanych Przygotujmy teraz procedur skáadowan zwi kszaj c o jeden wiek wszystkich osób nieb d cych peánoletnimi kobietami (listing 3.9). Zapiszmy j w bazie pod nazw AktualizujWiek i dodajmy do prawego panelu na zakáadce Telefony.dbml. Listing 3.9. Procedura skáadowana modyfikuj ca dane w tabeli ListaOsob ALTER PROCEDURE dbo.AktualizujWiek AS UPDATE ListaOsob SET Wiek=Wiek+1 WHERE NOT SUBSTRING(Imiú,LEN(Imiú),1)='a' OR Wiek<18 RETURN Aby j uruchomiü z poziomu C#, wystarczy do kodu dodaü instrukcj : bazaDanychTelefony.AktualizujWiek(); Zmiany w tabeli bazy danych b d wprowadzone natychmiast i bezpo rednio, tj. np. bez konieczno ci uruchamiania metody SubmitChanges instancji TelefonyDataContext. Z tego wynika te , e je eli wcze niej pobrali my kolekcj danych zapytaniem LINQ, nale y to teraz powtórzyü, aby uwzgl dniü aktualizacje. Wykonywanie dowolnych poleceþ SQL Pobieranie danych i ich modyfikacja za pomoc skáadowanych polece SQL nie jest mo e tym, co programi ci znaj cy LINQ zbytnio doceniaj . Warto jednak zwróciü uwag , e istnieje grupa czynno ci, które w SQL jest wykonaü najpro ciej. Przyjmijmy, e w naszej bazie danych tworzymy zbiór tabel dla ka dego nowego zarejestrowanego u ytkownika. Wówczas nie do przecenienia jest mo liwo ü przygotowania skáadowanej procedury zawieraj cej kod SQL tworz cy tabel i wypeániaj cy j danymi. W tym celu wystarczy dodaü now procedur skáadow (przykáad widoczny jest na listingu 3.10), dodaü j za pomoc O/R Designera do klasy TelefonyDataContext i wywoáaü w ko- dzie C#. Nazw i dane tabeli mo emy przekazaü przez parametry procedury. Pami - tajmy jednak, e nowa utworzona w ten sposób tabela nie b dzie zmapowana i w kon- sekwencji nie b dzie widoczna w obiekcie — instancji klasy TelefonyDataContext. Listing 3.10. Przykáadowa procedura skáadowa tworz ca tabel ALTER PROCEDURE dbo.TwórzNowæTabelú AS CREATE TABLE "Faktury" (Id INT, NrFaktury INT, Opis NVARCHAR(MAX)) INSERT INTO "Faktury" VALUES(1, 1022, 'Faktura za stycze 2008') INSERT INTO "Faktury" VALUES(1, 1022, 'Faktura za luty 2008') RETURN