1 LINQ. Zaawansowane programowanie internetowe Instrukcja nr 1

1 LINQ 1 Zaawansowane programowanie internetowe intern Instrukcja nr 1 1. Cel zajęć Celem zajęć jest zapoznanie się z technologią LINQ oraz tworzen...
Author: Patryk Woźniak
7 downloads 2 Views 1MB Size
1 LINQ

1 Zaawansowane programowanie internetowe intern Instrukcja nr 1

1. Cel zajęć Celem zajęć jest zapoznanie się z technologią LINQ oraz tworzeniem trójwarstwowej aplikacji internetowej.

2. Zadanie Proszę przygotować aplikację WWW, która: która • •



będzie pozwalała na generowanie prostych artykułów podzielonych na kategorie. W aplikacji mają być wyraźnie wydzielone warstwy: o dostępu do danych (odpowiadająca za komunikację z bazą danych) o biznesowej (odpowiadającej za wykonanie reguł biznesowych w aplikacji) o prezentacji (odpowiadającej za komunikację z użytkownikiem) komunikacja omunikacja z bazą danych ma się odbywać za pomocą technologii Linq To SQL

W tym celu należy wykonać odpowiednie kroki:

I. Stworzenie bazy danych a) Tworzymy my nową aplikację typu ASP.NET Web Application (jako nazwę należy przyjąć Zadanie 1.1) b) W celu utworzenia nowej bazy danych w oknie Solution Explorer klikamy prawym przyciskiem myszy na katalogu App_Data i z menu kontekstowego wybieramy opcję Add > New Item. Ite c) W wyświetlonym oknie dialogowym wybieramy opcję SQL Server Database, a jako nazwę pliku podajemy Artykuly.mdf i wciskamy przycisk Add.

2 Zaawansowane programowanie internetowe intern Instrukcja nr 1

d) Ponownie otwieramy okno Solution Explorer i klikamy dwukrotnie na nowej pozycji Artykuly.mdf w celu otwarcia okna edycji bazy danych. e) Klikając prawym przyciskiem myszy na węźle Tables i wybieramy opcję Add New Table. Wyświetlone zostanie okno edycji tabeli, które wypełniamy tak jak pokazano na rysunku poniżej

f)

Proszę pamiętać o ustawieniu klucza głównego tabeli na polu ID. Podobnie tworzymy drugą tabelę Artykuly i ustawiamy w niej następujące pola

g) Połączmy te dwie tabele relację Jeden do wielu. h) Zapiszmy wprowadzone zmiany.

II. Stworzenie

warstwy

dostępu

do

danych

a) W oknie SolutionExplorer tworzymy nowy katalog „DAL” „DA (Data Access Layer) i wszystkie pliki, o których będzie mowa w tym punkcie będziemy umieszczać w tym katalogu. b) Ponownie otwórzmy okno SolutionExplorer i klikając prawym przyciskiem myszy wybieramy opcję Add > New Item. c) Z grupy Data wybieramy opcję LINQ to SQL Classes, jako nazwę podajemy Artykuly.dbml i klikamy przycisk Add.

3 Zaawansowane programowanie internetowe intern Instrukcja nr 1

Stanowi to podstawę do utworzenia mapowania obiektowo – relacyjnego umożliwiającego wykonywanie zapytań LINQ to SQL. d) Otwieramy okno Server Explorer i przeciągamy z niego obie utworzone ut w bazie danych tabele, które umieszczamy w otwartym oknie projektanta mapowania obiektowo – relacyjnego. W efekcie w oknie tym powinny się pojawić następujące elementy:

Należy zauważyć, że VisualStudio automatycznie rozpoznało połączenie pomiędzy odpowiednimi tabelami. e) Ponownie otwórzmy okno SolutionExplorer i dodajmy do projektu nowy interfejs (Add > New Item > Code > Interface), który nazwiemy IArtykuly. Interfejsu wygląda następująco: public interface IArtykuly { List List > PobierzArtykulyZKategorii( int Kategoria); Artykul PobierzArtykul(int ID); void DodajArtykul(string tytul, string tresc, int Kategoria); void EdytujArtykul(string tytul, string tresc, int Kategoria, int ID); void UsunArtykul(int ID); } f)

Następnie, analogicznie, tworzymy drugi interfejs IKategorie: IKategorie public interface IKategorie { List List > PobierzWszystkie(); Kategoria PobierzKategorieWgID(int int ID); void DodajKategorie(string Nazwa, string Opis); void EdytujKategorie(string Nazwa, string Opis, int ID); void UsunKategorie(int ID); }

g)

Kolejno tworzymy dwie klasy pomocnicze:

4 Zaawansowane programowanie internetowe intern Instrukcja nr 1

public class Kategoria { public int ID { get; set; } public string Nazwa { get; set; } public string Opis { get; set; } public int LiczbaArtykulow { get; set; ; } } public class Artykul { public ublic int ID { get; set; } public string Tytul { get; set; } public string Tresc { get; set; } public int Kategoria { get; set; } public DateTime DataOstatniejModyfikacji { get; set; } public DateTime DataUtworzenia { get; ; set; } } Elementy te będą służyły do komunikacji pomiędzy poszczególnymi warstwami h) Następnie tworzymy klasę która będzie realizowała interfejs IArtykul Klasa ta będzie odpowiedzialna za komunikację z bazą danych. public class ArtykulLINQ_To_SQL : IArtykuly { public List > PobierzArtykulyZKategorii( int Kategoria) { using (Zadanie_1_1DataContext context = new Zadanie_1_1DataContext()) Zadanie_1_1DataContext  { var artykuly = from a in context.Artykulies where a.Kategoria == Kategoria select new Artykul { Tytul = a.Tytul, ID = a.ArtykulID };  return artykuly.ToList();  } }

5 Zaawansowane programowanie internetowe intern Instrukcja nr 1

public Artykul PobierzArtykul(int ID) { using (Zadanie_1_1DataContext context = new Zadanie_1_1DataContext()) Zadanie_1_1DataContext { try { var artykul = context.Artykulies.Single( a => a.ArtykulID == ID); return new Artykul { Tytul = artykul.Tytul, Tresc = artykul.Tresc, DataUtworzenia = artykul.DataUtworzenia, DataOstatniejModyfikacji = artykul.DataOstatniejModyfikacji, rtykul.DataOstatniejModyfikacji, Kategoria = artykul.Kategoria, ID = artykul.ArtykulID }; } catch { return null; } } } public void DodajArtykul(string tytul, string tresc, int kategoria) { using (Zadanie_1_1DataContext context = new Zadanie_1_1DataContext()) Zadanie_1_1DataContext { Artykuly art = new Artykuly { Kategoria = kategoria, Tytul = tytul, Tresc = tresc, DataOstatniejModyfikacji = DateTime.Now, DateTime DataUtworzenia = DateTime.Now }; context.Artykulies.InsertOnSubmit(art); context.SubmitChanges(); } }

6 Zaawansowane programowanie internetowe intern Instrukcja nr 1

public void EdytujArtykul(string tytul, string tresc, int kategoria, int ID) { using (Zadanie_1_1DataContext context = new Zadanie_1_1DataContext()) Zadanie_1_1DataContext { var artykul = context.Artykulies.Single( a => a.ArtykulID == ID); artykul.Tytul = tytul; artykul.Tresc = tresc; artykul.Kategoria = kategoria; artykul.DataOstatniejModyfikacji = DateTime.Now; context.SubmitChanges(); } } public void UsunArtykul(int ID) { using (Zadanie_1_1DataContext context = new Zadanie_1_1DataContext()) Zadanie_1_1DataContext { var artykul = context.Artykulies.Single( a => a.ArtykulID == ID); context.Artykulies.DeleteOnSubmit(artykul); context.SubmitChanges(); } } }

 Utworzenie klasy kontekstu. Instrukcja ta zawarta jest w bloku using w celu automatycznego zwolnienia zasobów w momencie, gdy nie są już potrzebne  Przykład typowego zapytania LINQ to SQL realizującego zarówno selekcję wierszy i projekcję kolumn z tabeli bazy danych.  Ponieważ instrukcja w linii oznaczonej jako  tworzy obiekt klasy IEnumerable, konieczne jest wywołanie funkcji ToList() w celu wykonania zapytania i wygenerowania wymaganej listy obiektów. i)

Kolejno proszę utworzyć klasę KategoriaLINQ_To_SQL (na obraz i podobieństwo klasy ArtykulLINQ_To_SQL)

7 Zaawansowane programowanie internetowe intern Instrukcja nr 1

III. Stworzenie tworzenie warstwy biznesowej a) Otwieramy okno SolutionExplorer i dodajmy do projektu (do katalogu kat głównego) dwie nowe klasy KategorieBLL i ArtykulyBLL. Klasy te będą stanowiły naszą warstwę biznesową. Warstwa ta powinna zawierać całą logikę aplikacji (sprawdzanie poprawności danych, autoryzację itd.) [DataObject DataObject] public class KategorieBLL : IKategorie { IKategorie _kategorie;



public KategorieBLL() : this(new KategorieLINQ_To_SQL()) KategorieLINQ_To_SQL {}  public KategorieBLL(IKategorie kategorieDAL) { _kategorie = kategorieDAL; } [DataObjectMethod DataObjectMethod(DataObjectMethodType.Select, .Select, true)]  public List > PobierzWszystkie() { return _kategorie.PobierzWszystkie(); } [DataObjectMethod DataObjectMethod(DataObjectMethodType.Select, .Select, false)] public Kategoria PobierzKategorieWgID(int int ID) { return _kategorie.PobierzKategorieWgID(ID); } [DataObjectMethod DataObjectMethod(DataObjectMethodType.Insert, .Insert, true)] public void DodajKategorie(string Nazwa, string Opis) { _kategorie.DodajKategorie(Nazwa, Opis); } [DataObjectMethod DataObjectMethod(DataObjectMethodType.Update, .Update, true)] public void EdytujKategorie(string Nazwa, string Opis, int ID) { _kategorie.EdytujKategorie(Nazwa, Opis, ID); } [DataObjectMethod DataObjectMethod(DataObjectMethodType.Delete, .Delete, true)] public void UsunKategorie(int ID) { _kategorie.UsunKategorie(ID); } }

8 Zaawansowane programowanie internetowe intern Instrukcja nr 1

W przedstawianej tutaj prostej aplikacji klasa ta stanowi jedynie implementację interfejsu IKategorie. Klasa i jej metody opisane są odpowiednimi atrybutami, które pozwalają na łatwiejsze podłączenie jej z obiektami typu ObjectDataSet znajdującymi się w warstwie prezentacji.

 Atrybut ten informuje Visual Studio, że klasa ta jest odpowiedzialna odp za dostarczenie danych dla warstwy prezentacji.  Klasa zawiera dwa konstruktory. Pierwszy – domyślny – wymagany jest przez Visual Studio, drugi umożliwia „wstrzyknięcie” obiektu umożliwiającego połączenia z bazą danych.  Atrybut opisujący metody DataObjectMethod pozwala na określenie jej przeznaczenia. Składnia tego atrybutu jest następująca: DataObjectMethod(DataObjectMethodType, bool) Pierwszy parametr określa przeznaczenie metody, drugi czy jest to metoda domyślna czy nie. b) Proszę stworzyć klasę stanowiącą warstwę biznesową dla tabeli Artykuły. c) Proszę przebudować projekt (Build > Build Solution).

IV. Stworzenie warstwy prezentacji a) W stronie „master page” proszę zmienić komponent menu tak aby wskazywał na dwie strony: kategorie.aspx i artykuly.aspx

b) Proszę dołączyć do projektu nową stronę kategorie.aspx c) Na stronie tej proszę umieścić następujące komponenty i nadać im nazwy podane w nawiasach: nawiasach • • • • •

LinkButton (NowaKategoria) DetailsView (KategoriaDV) GridView (KategorieGV) Object ObjectDataSource (KategoriaODS) ObjectDataSource (KategorieODS)

9 Zaawansowane programowanie internetowe intern Instrukcja nr 1

d) Klikamy na pierwszy komponent typu ObjectDataSource i rozwijamy okienko Tasks, Tasks z którego wybieramy opcję Configure Data Source

e) W oknie dialogowym wybieramy klasę, która będzie źródłem danych dla naszego obiektu. Jeżeli zaznaczymy opcję „Show only data components” powinny pojawić się tylko te klasy, które oznaczyliśmy atrybutem [DataObject]. Wybieramy klasę KategorieBLL i klikamy przycisk Next.

10 Zaawansowane programowanie internetowe intern Instrukcja nr 1

f)

Następnie możemy ustawić z jakich metod wybranej wcześniej klasy ma korzystać źródło danych przy wykonywaniu operacji pobierania i edycji danych. Zauważmy że odpowiednie metody zostały już wybrane dzięki ustawionym wcześniej atrybutom. Zmieńmy jednak metodę w zakładce „Se „Select” na „PobierzKategorieWgID”, pozostałe wpisy pozostawmy bez zmian. Klikamy przycisk Next.

g)

Ponieważ wybrana metoda „PobierzKategorieWgID” ma przypisany parametr w następnym oknie jesteśmy proszeni o wybranie źródła wartości dla niego. W naszym przypadku wybieramy wartości tak jak pokazano na rysunku poniżej (przy założeniu, że komponent GridView nazwany jest KategorieGV).

11 Zaawansowane programowanie internetowe intern Instrukcja nr 1

h) Klikamy przycisk „Finish”. „F i) Następnie klikamy raz jeszcze na modyfikowanym w poprzednich krokach obiekcie i w oknie „Properties” „Properties” zmieniamy wartość właściwości „OldValuesParameterFormatString” z „orginal_{0}” na „{0}”. j) Następnie klikamy na obiekcie typu DetailsView, rozwijamy okienko Task, w którym ustawiamy opcje tak jak pokazano na rysunku poniżej i klikamy opcje „EditFields”. ds”.

k)

W wyświetlonym oknie dialogowym w okienku: „Selected Fields” usuwamy pozycje tak aby pozostały tylko: „Nazwa”, „Opis”, „CommandField”. Następnie klikamy na „CommandField” i w oknie „„CommandField properties” odnajdujemy pozycję NewText, z której usuwamy zawartość.

12 Zaawansowane programowanie internetowe intern Instrukcja nr 1

l) Klikamy na przycisk OK. w celu zamknięcia okna. m) W oknie Properties dla pozycji „DataKeyNames” przypisujemy wartość „ID”. n) Następnie w podobny sposób proszę skonfigurować drugi obiekt typu ObjectDataSet, przy czym w zakładce „Select” proszę wybrać metodę „PobierzWszystkie”. o) Obiekt GridView proszę podłączyć do drugiego obiektu typu ObjectDataSet i skonfigurować rować tak aby możliwe było wybranie opcji Edit lub Delete. Proszę również ustawić właściwość „DataKeyNames” na wartość „ID”

p) Następnie proszę przypisanie do odpowiednich komponentów następujących metod obsługi zdarzeń: •

LinkButton (NowaKategoria) – Click protected void NowaKategoria_Click( object sender, EventArgs e) { KategoriaDV.ChangeMode(DetailsViewMode.Insert); KategoriaDV.ChangeMode(DetailsViewMode KategoriaDV.Visible = true; } Metoda ta ma za zadanie wyświetlić komponent DetailsView i przełączyć go automatycznie w tryb wprowadzania nowych danych.



GridView (KategorieGV) – RowEditing protected void KategorieGV_RowEditing( object sender, GridViewEditEventArgs e) { KategorieGV.SelectedIndex = e.NewEditIndex; KategoriaDV.ChangeMode(DetailsViewMode DetailsViewMode.Edit); KategoriaDV.Visible = true; e.Cancel = true; } Metoda ta ma za zadanie wyświetlić komponent DetailsView i przełączyć go automatycznie w tryb wprowadzania edycji danych dla wiersza wybranego w GridView

13 Zaawansowane programowanie internetowe intern Instrukcja nr 1



DetailsView (KategoriaDV) – ModeChanging protected void KategoriaDV_ModeChanging( object sender, DetailsViewModeEventArgs e) { if (e.NewMode == DetailsViewMode.ReadOnly) .ReadOnly) KategoriaDV.Visible = false; } Metoda ta ma za zadanie ukryć komponent DetailsView, w momencie gdy użytkownik zatwierdzi lub anuluje anuluje edycję danych.

q) Następnie proszę o przygotowanie drugiej strony Artykuly.aspx Artyku tak aby wyglądała mniej więcej jak na rysunku poniżej:

Komponent DropDownList (Kategoria) ma pozwolić na wybranie kategorii, kategorii z której mają być wyświetlone artykuły. Pozostałe komponenty powinny się zachowywać mniej więcej tak jak na poprzedniej stronie. Mała podpowiedź: Ponieważ w komponencie DetailsView ma nie być pozycji Kategoria, jej wartość musi być pobierana z komponentu DropDownList. Aby wartość ta była dołączona dołącz do zestawu danych przekazanego do warstwy biznesowej konieczne jest przypisanie do komponentu DetailsView dwóch metod obsługi zdarzeń: ItemInserting oraz ItemUpdating, w których wpisujemy odpowiednio: • •

e.Values["Kategoria"] e.Values[ ] = KategorieDDL.SelectedValue; e.NewValues[ e.NewValues["Kategoria"] ] = KategorieDDL.SelectedValue;

14 Zaawansowane programowanie internetowe intern Instrukcja nr 1

V. Zadania do samodzielnego wykonania Jeżeli wystarczy Państwu czasu ☺ to na zajęciach, jeżeli nie to w domu proszę – w ramach powtórzenia – o rozbudowanie tej aplikacji o technologię asunchronicznego przesyłu danych AJAX oraz dołączenie do niej strony, która umożliwiła by przeglądanie artykułów w trybie tylko do odczytu.

15 Zaawansowane programowanie internetowe intern Instrukcja nr 1