1.02k likes | 1.36k Views
Zaawansowane aplikacje internetowe – ASP.NET 2.0 / 3.5 - PROJEKT. Prowadzący: Jarosław Kurek kurekj@iem.pw.edu.pl. Agenda. I Transakcje II Gupowy insert (bulk copy) III ORM na przykładzie MyGeneration IV Nowości w C# 3.5 V LINQ VI Web Serwisy VII Technologią Ajax VIII ASP.NET AJAX.
E N D
Zaawansowane aplikacje internetowe – ASP.NET 2.0 / 3.5 - PROJEKT Prowadzący: Jarosław Kurek kurekj@iem.pw.edu.pl
Agenda • I Transakcje • II Gupowy insert (bulk copy) • III ORM na przykładzie MyGeneration • IV Nowości w C# 3.5 • V LINQ • VI Web Serwisy • VII Technologią Ajax • VIII ASP.NET AJAX
Dane i dostęp do danych c.d.Transakcje • Transakcje - zbiór operacji na bazie danych, które stanowią w istocie pewną całość i jako takie powinny być wykonane wszystkie lub żadna z nich (chyba, że rollback) • Przykładem transakcji może być transakcja bankowa jaką jest przelew. Muszą tu zostać dokonane 2 operacje - zabranie pieniędzy z jednego konta oraz dopisanie ich do drugiego. W przypadku niepowodzenia żadna z tych operacji nie powinna być zatwierdzona, gdyż zajście tylko jednej powodowałoby nieprawidłowości w bazie danych (pojawienie się lub zniknięcie pieniędzy).
Dane i dostęp do danych c.d.Transakcje • Transakcje powinny spełniać zasady ACID (Atomicity, Consistency, Isolation, Durability - Atomowość, Spójność, Izolacja, Trwałość). • Atomowość- niepodzielność: każda transakcja zostanie wykonana w całości lub w ogóle • Spójność – po wykonaniu transakcji baza będzie spójna, transakcje nie naruszają integralności • Izolacja – w zależności od poziomu izolacji możemy się spodziewać różnych anomalii, w przypadku realizacji dwóch współbieżnie wykonujących się transakcji • Trwałość – gwarancja trwałości wykonanych operacji
Dane i dostęp do danych c.d.Transakcje • Poziom izolacji wprowadzany do znalezienia kompromisu pomiędzy współbieżnością a poprawnością wykonania transakcji • Poziomy izolacji: • READ UNCOMMITTED • Dopuszczenie odczytywania danych, które zostały zmienione przez niezatwierdzone transakcje – może czytać dodane wiersze które później będą wycofane (Czytanie na brudno) • Najniższy poziom izolacji • READ COMMITED • Odczytuje tylko zatwierdzone dane • Brak gwarancji, że dane odczytane nie zostaną zmienione przez inną transakcję • Problem niepowtarzalnego odczytu – gdy ta sama dana jest czytana dwa razy a w międzyczasie inna transakcja ją modyfikuje
Dane i dostęp do danych c.d.Transakcje • Poziomy izolacji c.d.: • SERIALIZABLE • Odczytuje wyłącznie dane zatwierdzone • Do momentu zakończenia transakcji żadna dana nie zostanie zmieniona przez inną transakcje • Blokuje dostęp do tabeli • Zapewnia szeregowalność • REPEATABLE READ • Tak samo jak SERIALIZABLE – tylko, że blokuje dostęp do danych a nie całej tabeli • Pojawia się problem „fantomów” – gdy jedna transakcja czyta dane, druga w tym samym czasie dodaje lub uaktualnia • FANTOM (złudne dane) Ilustruje to przykład: transakcja wyszukuje rachunki o saldzie powyzej 10.000zł. W ramach jednej transakcji wykonujemy dwa razy odczyt. Miedzy pierwszym a drugim inna transakcja dodaje nowy rachunek o saldzie 20.000zł. Spełnia on warunek zapytania rekord pojawi się w wyniku jako fantom.
Dane i dostęp do danych c.d.Transakcje Porównanie poziomów izolacji:
Dane i dostęp do danych c.d.Transakcje • Commit – zatwierdza transakcje • Save – tworzy punkt kontrolny transakcji do którego można wrócić poprzez rollback • Rollback- przywracanie transakcji do danego punktu kontrolnego. • Transakcję podłączamy do otwartego połączenia oraz sqlCommand
Dane i dostęp do danych c.d.bulk operations • Bulk operations – są to operacje polegające na wykonanie wielu operacji na bazie danych „jednocześnie”. • Bardzo wydajny sposób na wrzucenie tysięcy rekordów np. pomiarów bez wywołania tysięcy insertów. • Bardzo prosty sposób obsługi: • Wypełnić dane – datatable • Połączyć się z bazą • Opcjonalnie zmapować kolumny source->destination • Wskazać tabele (destination) • Zapis do bazy
Dane i dostęp do danych c.d.bulk operations • SqlBulkCopy– pozwala na wrzucenie wielu rekordów danych z DataTable do bazy danych za pomocą jednego wywołania • ColumnMappings.Add(„kol_źród", „kol_docel") – pozwala na mapowanie kolumn w datatable i w tabeli bazy danych • DestinationTableName – docelowa nazwa tabeli do której zapisujemy dane • WriteToServer(DataTable) – wykonuje zapisz do bazy wymienionej jako argument datatable.
Dane i dostęp do danych c.d.Procedury składowane • Procedury składowane nie należą do standardu SQL, lecz do T-SQL(MSSQL) lub PL/SQL (Oracle), ZALETY: • Większa wydajność: Procedury są przechowywane w bazie w postaci skompilowanej i zoptymalizowanej. Dlatego procedury takie wykonują się szybciej niż odpowiedni kod SQL w postaci tradycyjnej. Dodatkowo jeśli mamy do czynienia z sytuacją, w której aplikacja łączy się ze zdalnym serwerem baz danych to zastosowanie procedur składowanych może zmniejszyć ruch w sieci komputerowej, gdyż zamiast długich zapytań transportujemy w sieci tylko nazwy procedur i ewentualnie parametry wejściowe.
Dane i dostęp do danych c.d.Procedury składowane ZALETY c.d.: • Większe bezpieczeństwo: Parametry wejściowe w procedurach składowanych mają zadeklarowane typy. Powoduje to, że aplikacje wykorzystujące procedury składowane są bardziej odporne na wstrzykiwanie kodu (SQL injection) - jedną z technik włamań stosowanych głównie w aplikacjach internetowych. • Modularyzacja kodu. Stosowanie procedur składowanych powoduje, że w kodzie aplikacji zamiast (czasem złożonych) zapytań SQL pojawiają się nazwy procedur, które o wiele łatwiej mogą opisywać jej funkcjonalność.
Dane i dostęp do danych c.d.Procedury składowane ZALETY c.d.: • Łatwiejsza migracja do innych środowisk. Jeśli chcemy przenieść aplikację do innego środowiska programistycznego pozostając przy tym samym serwerze baz danych, to jeśli nasza aplikacja ma część logiki biznesowej zaimplementowanej w postaci procedur składowanych to operacja ta będzie łatwiejsza, dlatego, że po prostu mniej kodu będzie do przeniesienia.
Dane i dostęp do danych c.d.Procedury składowane - podstawy • Szkielet procedury: CREATE PROCEDURE @nazwa_parametru typdanych(długośc),… As DECLARE @nazwa_zmiennej typdanych(długość) BEGIN Wyrażenie SQL END • Nadawanie wartości zmiennym SELECT @zmienna=3 • Wyświetlanie zmiennej PRINT @zmienna
Dane i dostęp do danych c.d.Procedury składowane - przykład create procedure [dbo].[InsertOsoba] @Companyname varchar(101), @contactname varchar(101) as begin insert into tb_osoba(companyname,contactname) values(@Companyname,@contactname) select @@identity end
Dane i dostęp do danych c.d.Procedury składowane – użycie w ASP.NET • Należy zmodyfikować typ wykonania SqlCommand: ...commandType = CommandType.StoredProcedure; • Zamiast polecenia SQL podać nazwę procedury: ...CommandText = "InsertOsoba"; • Zdefiniować parametry wejściowe procedury: ...Parameters.AddWithValue("@Companyname", "Jarosław");
ORM (Object Relational Mapping) • ORM to pomost między logiką biznesową a relacyjną strukturą bazy danych • Odwzorowuje tabele, procedury składowane, widoki na obiekty w logice biznesowej • Zmniejsza rozmiar kodu przez operowanie obiektami, w których zaszyte są operacje CRUD • Podczas wczytywania obiektu, automatycznie ładowane są obiekty powiązane- jeżeli są wymagane
ORM (Object Relational Mapping) • Możliwość tworzenia złożonych zapytań. ORM dostarcza Object Oriented Query Language, który później jest tłumaczony na polecenia SQL do konkretnego SZBD • Concurrency support - ORM obsługuje konkurencyjność w przypadku pracy „multiuser” – przy edytowaniu rekordów. • Cache managment – umożliwia buforowanie obiektów • Transaction management and Isolation – obsługują transakcje oraz poziomy izolacji
MyGeneration (ORM) • Darmowy ORM dla .NET (http://www.mygenerationsoftware.com) • Wykorzystuje architekturę dOOdads dla .NET (C# oraz VB.NET) • dOOdads wspiera :Microsoft SQL, Oracle, Firebird, Access, PostgreSQL, VistaDB, SQLite, MySQL • Generator kodu dla czterech języków JScript, VBScript, C#, VB.NET w oparciu o szablony baz danych. • Obecna wersja MyGeneration 1.3.0.3 dostępny pod http://sourceforge.net/projects/mygeneration/
MyGeneration (ORM)instalacja / konfiguracja • Instalacja MyGeneration z http://www.mygenerationsoftware.com • Utworzenie biblioteki MyGeneration.dOOdads.dll w VS.NET MyGeneration\Architectures\dOOdads\CSharp\MyGeneration.dOOdads • W folderze DbAdapters dla określonej bazy danych ustawić „Build Action" in "Properties" "Compile” W przypadku MSSQL: - SqlClientDynamicQuery.cs - SqlClientEntity.cs • Skompilować jako release.
MyGeneration (ORM) - konfiguracja • Przed generacją należy zdefiniować ustawienia domyślne
MyGeneration (ORM) BLL i DAL • W projekcie wykorzystującym ORM, dodać referencję MyGeneration.dOOdads.dll • Utworzyć w web.config connectionstring do bazy danych <appSettings> <add key="dbConnection" value="Server=localhost;User ID=user;password=haslo;database=Northwind"/> • Utworzyć folder na klasy DAL (Data Access Layer) • Utworzyć folder na klasy BLL (Business Logic Layer) • Wygenerować procedury składowane na operacje CRUD w template browser->MS SQL Server->Script Insert, Update,Delete procedures for SQL Server.
MyGeneration (ORM) BLL i DAL • Po wygenerowaniu skryptu procedur CRUD, należy je wykonać. • Należy wygenerować klasy dostępowe do bazy DAL (Business Entity) – dodać je do folderu DAL • Należy wygenerować klasy BLL concrete class – dodać je do folderu BLL • Przy generacji należy podać namespace
ObjectBroker ObjectSpaces ObjectSpark Objectz.NET OJB.NET OPF.Net (Object Persistent Framework) ORM.NET Pragmatier Data Tier Builder RapTier Sisyphus Persistence Framework TierDeveloper Bob.NET ObjectPersistor.NET Genome Inne ORM’y • .NET Persistence • BBADataObjects • DataObjects.NET • Data Tier Modeler for .NET • DotNorm • Eldorado.NET • Enterprise Core Objects (ECO™) • Entity Broker • eXpress Persistent Objects for .NET • FastObjects.NET • JC Persistent Framework • LLBLGen Pro • ModelWorks • Nhibernate • Nolics.NET • Norm • Norpheme
Nowości w C# 3.5 • Niejawne typowanie zmiennych lokalnych • Automatyczne properties • Metody rozszerzające • Metody częściowe (partial methods) • Automatyczne inicjalizowanie obiektów • Anonimowe typy • Wyrażenie Lambda
Niejawne typowanie zmiennych lokalnych • zmienna musi być zainicjalizowana przy deklaracji • może być zadeklarowane wyłącznie w ciele metody (lokalnie) • jeśli wskazuje na typ „właściwy”, to zostaje zamieniony na typ na etapie kompilacji • zalety: • dla osób lubiących zwinność języków typowanych dynamicznie • oszczędza czas
Niejawne typowanie zmiennych lokalnych • Zmienna lokalna • Nie może być argumentem metody, zwracana • Nie może być polem klasy • Musi być inicjalizowana podczas deklaracji • Nie może przyjąć wartości null • Może być typem referencyjnym • Jest silnie typowana, nie może zmieniać typu podczas wykonywania programu tak jak w VBscript, Perl
Automatyczne properties • W C# 3.0 jest możliwość zastosowania automatycznego • set i get muszą być deklarowane w parze • kod jest generowany na etapie kompilacji • zaleta: zwięzłość kodu Np. public double TotalPurchases { get; set; } lub public string Name { get; private set; } // tylko do odczytu
Metody rozszerzające • pozwalają rozszerzać funkcjonalność istniejących klas bez potrzeby rekompilacji • muszą znajdować się w statycznej klasie i być statycznymi metodami • słówko this • dostęp wyłącznie do publicznych pól klasy rozszerzanej • nie można nadpisywać istniejących metod public static class myMetodaRozrz { public static int Convert2Str(this int a) { return a.ToString(); } }
Metody częściowe (partial methods) • Od C# 2.0 możliwe jest używanie partial class • Od C# 3.5 możliwe jest używanie partial method • Ograniczenia: • Muszą być zdefiniowane w tej samej partial class • Metody nie mogą zwracać zmiennych (void) • Metody są niejawnie ustawione jako private • Mogą zawierać argumenty • Mogą być statyczne
Metody częściowe (partial methods) partial class A { string _name; partial void OnNameChanged(); public string Name { set { _name = value; OnNameChanged(); } } } partial class A { partial void OnNameChanged() { // implementacja } }
Szybkie Inicjalizowanie obiektów • Automatycznie można przekazać wartości properties i polom publicznym Standardowo: Point p = new Point(); p.X = 2; p.Y = 3; Np.: var objPoint = new Point { X = 30, Y = 30 }; Point objPoint = new Point { X = 30, Y = 30 };
Szybkie Inicjalizowanie obiektów • Automatycznie można przekazać wartości properties i polom publicznym Standardowo: Point p = new Point(); p.X = 2; p.Y = 3; Np.: var objPoint = new Point { X = 30, Y = 30 }; Point objPoint = new Point { X = 30, Y = 30 };
Anonimowe typy • W przypadku szybkiego stworzenia struktury, klasy z paroma polami bez metod, zdarzeń,… Przykład: • var mojCar = new { Kolor = „zielony", Marka = "Saab", maxV = 220 }; • Typy anonimowe dziedziczą po System.Object • Pola anonimowych typów są zawsze read-only • Anonimowe typy są niejawnie sealed • Wykorzystują domyślny konstruktor
Wyrażenie Lambda • Wyrażenie lambda korzysta z nowego operatora => • Spełniają podobna rolę jak metody anonimowe (C# 2.0) delegate double Function(double c); static double Apply(double a, Function f) { } utworzenie metody anonimowej: Apply(5.5, delegate(double x){ return x*x; } Ogólna składania wyrażenia lambda: (parametry)=>wartość; (parametry)=>{instrukcja;} Przykłady: (int n)=>n+2 (x,y)=>x==y N=>{Response.Write(N.ToString());} • Mogą one być przypisane do delegacji
Wyrażenie Lambdadelegacje • Obiektowa wersja wskaźników funkcji • Delegacje tworzą szkielet metod na które mogą wskazywać- deklaracja musi być identyczna Delegat: Np. delegate double mojdeleg(int a, int b); Oraz jakaś metoda: private double multiply(int AA, int BB) { return AA * BB; } Wykorzystanie: mojdeleg objdel = new mojdeleg(multiply); double res = objdel(3, 4);
Wyrażenie Lambdadelegacje • Deklaracja delegata: delegate bool porownaj(double x double y); • Wykorzystanie wyrażenia lambda: porownaj objPor=(x,y)=>x==y; Można by było zapisać to standardowo: private bool sprawdz(double x,double y) { return x==y; } porownaj objPor=porownaj(sprawdz);
(Language Integrated Query) LINQ • LINQ – zintegrowany język zapytań • IDEA: • Wykorzystać pochodzącą z języka SQL intuicję budowania zapytań i pobierać w ten sposób dane z dowolnego źródła • Przenosi programistę na wyższy poziom abstrakcji w postrzeganiu danych • Zapytania są formułowane w jednej linii z zachowaniem prostoty i intuicyjności zapytań SQL • Technologie: • LINQ to objects • LINQ to SQL • LINQ to DataSet • LINQ to XML
(Language Integrated Query) LINQ • LINQ korzysta z metod rozszerzających W przestrzeni System.Query zdefiniowany został zbiór taki metod jak: select, where, orderby i zostały dodane do intefejsu IEnumerable<T> implementowanego przez wszystkie kolekcje • Wyrażenia lambda służą do definicji kryteriów • Zwracane przez LINQ wartości mogą być niewiadomowego typu i dlatego przypisujemy je do słowa kluczowego var, uzyskuje on konkretny typ dopiero przy inicjacji • Podczas kompilacji metody rozszerzone są zamieniane na wywołania metod statycznych na rzecz klasy System.Linq.Enumerable, a wyrażenia lambda na odpowiednie delegacje
LINQ to objects • Kolekcje platformy .NET. Które implementują interfejs IEnumerable<T> mogą być źródłem danych w technologii LINQ to Objects • Do tego interfejsu zostały dodane metody rozszerzające LINQ Pobieranie danych: Select,SelectMany Sortowanie: Orderby,ThenBy,OrderByDescending, ThenbyDescending, Reverse Filtrowanie: Where Operacje arytmetyczne: Aggregate,Average,Count,Max,Min,Sum Konwersja: Cast,OfType,ToArray,ToDictionary,ToList,ToLookup Pobieranie elementu:Element,ElementAt,First,Last,… Porównanie: EqualAll Grupowanie:Groupby Łączenie: Join Kwantyfikatory: All, Any, Contains Operacje na zbiorach: Concat,Distinct,Except,Union • Można zatem filtrować, sortować, analizować, łączyć z inną kolekcją
LINQ to objects -przykład var listaosob=from osoba in ListaOsob where osoba.Wiek>20 orderby osoba.Wiek select new{osoba.Imie,osoba.Nazwisko}; Operatory LINQ „typ” var Typ anonimowy Nowy sposób inicjacji obiektów
LINQ to objects • Prezentacje danych: foreach(var osoba in listaosob) { Response.Write(osoba.Wiek+” ”+osoba.Imie); } • Kalkulacje: Response.Write(listaosob.Max(osoba=>osoba.Wiek); • Wybór elementu var najstarszaOsoba = listaosob.Single(osoba=>(osoba.Wiek==listaosob.max(osoba1=>osoba1.wiek))) • Testowanie danych: bool test =listaosob.All(osoba=>osoba.Wiek>20);
LINQ to objects • Łączenie zbiorów danych: var listaosobpelno=from osoba in listaosob where osoba.Wiek>18 orderby osoba.Wiek select new{osoba.Imie,osoba.Wiek}; var listakobiet=from osoba in listaosob where osoba.Imie.EndsWith(„a”) select new{osoba.Imie,osoba.Wiek}; var listapelnmezczyzn=listaosobpelno.Concat(listakobiet); var listapelnmezczyzn=listaosobpelno.Concat(listakobiet).Distinct(); iloczyn dwóch zbiorów: var listapelnmezczyzn=listaosobpelno.Intersect(listakobiet); nie będącymi kobietami: var listapelnmezczyzn=listaosobpelno.Except(listakobiet);
LINQ to SQL • Do łączenia używamy obiekt DataContex (współpraca z MS SQL) • Klasa DataContext jest główną bramą do technologii LINQ to SQL • Brama ta wymaga „strażnika” – klasa encji • Klasa encji odzwierciedla całą strukturę tabeli za pomocą atrybutów. • Pola klasy połączone są z polami tabeli (kolumnami) • Klasa encji pozwala na kontrolowanie typów w tabeli