480 likes | 644 Views
Efektywne wykorzystanie danych w .NET. Tomasz Kopacz. O czym będzie . Część I Jak pisać przy użyciu .NET, SQL-a i MSDE Podstawowe obiekty DataSet DataBinding Część II Jak wykorzystać MSDE we własnej aplikacji. Kilka słów o połączeniu. IConnection Pula
E N D
Efektywne wykorzystanie danych w .NET Tomasz Kopacz
O czym będzie • Część I • Jak pisać przy użyciu .NET, SQL-a i MSDE • Podstawowe obiekty • DataSet • DataBinding • Część II • Jak wykorzystać MSDE we własnej aplikacji
Kilka słów o połączeniu • IConnection • Pula • Mapuje po dokładnej postaci ConnectionString • Dodatkowe parametry: • Connection Lifetime; Max Pool Size / Min Pool Size; Pooling=‘false’ • POŁĄCZ, ZRÓB CO TRZEBA I ODŁĄCZ JAK NAJSZYBCIEJ • Na raz jedno polecenie przy użyciu jednego IConnetion
Połączenie i hasło SqlConnection db = new SqlConnection(„Data Source=localhost; Integrated Security=SSPI;Initial Catalog=Northwind"); … password=jan;user id=jan”); … db.Open(); • Naturalne miejsce • WebForms -> web.config • WinForms -> plikExe.config • Hasło czystym tekstem??? • Zakodować • Rijandel • System.Convert.ToBase64String • DPAPI – zajrzeć nawww.gotdotnet.com
Główne obiekty użytkowe • IDataCommand • IDataReader • Jednokierunkowy kursor tylko do odczytu • Generowany przez IDataCommand • DataSet • Baza danych po stronie aplikacji klienckiej • Wypełniany przez IDataAdapter • Polecenia IDataCommand • W „środku” wykorzystuje IDataReader • XML • Synchronizacja • Transakcje
DataSet a DataReader • Nie można powiedzieć jednoznacznie „który lepszy” • IDataReader • Szybki odczyt ale „jednokierunkowy” • Brak mechanizmów aktualizacji • Też „databinding” • irr(”MojePole”)… • DataSet • Gdy potrzebna tymczasowa kopia (cache) • XML z przyległościami • Model bezpołączeniowy
Obsługa dużych obiektów (BLOB) • Nie chcemy na raz całego obiektu • Jeżeli tylko do odczytu • IDataReader • SequentialAccess + GetBytes() • Fragmenty: • Wsparcie ze strony MS SQL • TEXTPTR –varbinary(16) • READTEXT tabela.kolumna ptr przesunięcie wielkość
IDataReader? • IDataReader • Scenariusz: strona aspx z dynamicznie generowaną tabelą na podstawie IDataReader • Każde odświeżenie strony to zapytanie do bazy • Mały koszmarek: if (!irr.IsDBNull(irr.GetOrdinal(„Pole”))…
DataSet i Cache • „Globalny DataSet” • ASP.NET / obiekty biznesowe • Drzewo kategorii, menu, coś „półstatycznego” DataSet GetMenu() { DataSet menu=Cache("MenuDS"); if(menu==null) { SqlDataAdapter da; //I zainicjować itp… menu=new DataSet(); da.Fill(menu); Cache("MenuDS")= menu; } return menu; }
DataSet DataSet, DataAdapter i ADO.NET Baza danych 1 Klient tworzyżądanie wyświetlenia strony Tworzenieobiektów SqlConnection i SqlDataAdapter 2 SqlConnection Wypełnienie DataSet z DataAdapter i zamknięcie połączenia 3 SqlDataAdapter Zwraca DataSet do klienta 4 Zmiana informacji przez użytkownika 5 Provider Aktualizacjadanych DataSet 6 Wykorzystanie SqlDataAdapter do otwarcia SqlConnection, aktualizacja danych w bazie i zamknięcie połączenia 7 Kontrolka DataGrid Klient
DataSet • Odwzorowanie bazy danych, ale… • Podzbiory elementów • Synchronizacja zmian • Rada: • Baza i niezależny DataSet jako obiekt pomocniczy - biznesowy
DataSet – projektant lub kod • Customer, Invoice, InvoiceItem, Product • Uwaga! Projektujemy więzy i relacje! • UniqueConstraint • ForeginKeyConstraint • DeleteRule,UpdateRule • (AcceptRejectRule) • Mocna kontrola typów
Relacje • Ustawiać tylko te co są potrzebne do nawigacji • Relacja rodzic – potomek DataRelation rel=ds.Relations.Add( "TestRel", ds.Invoice.Columns["id"], ds.InvoiceItem.Columns["id_inv"]) DataColumn[] aParent= { ds.Tables[0].Columns[0], ds.Tables[0].Columns[1] } DataColumn[] aChild= { …} ds.Relations.Add("TestRel",aParent,aChild,true)
Relacje - poruszanie się • GetParentRow/GetChildRows ((MainDS.Invoice)ds.InvoiceItem[0].GetParentRow(rel)) .inv_date… ds.Invoice[0].GetChildRows(rel).Length…
Triggery • RowChanging, RowChanged • ColumnChanging, ColumnChanged • RowDeleting, RowDeleted • Stan DataRowAction • Add, Change, Commit, Delete, Rollback • Nothing
Pola wyliczeniowe • Generalnie szybkie • Małe kłopoty z DataAdapter • Można dodać do DataSet po wypełnieniu • Język – patrz MSDN - temat DataColumn.Expression Property DataColumn col=new DataColumn("TotalPrice"); col.DataType=typeof(decimal); col.Expression="cnt * value"; ds.InvoiceItem.Columns.Add(col); …ds.InvoiceItem[0]["TotalPrice"]
Ładowanie danych • Ładowanie danych • BeginLoadData • DataTable.LoadDataRow(tablica,true) • EndLoadData – włącza, wczytane sprawdza! • EnforceConstraints
DataSet i XML • XMLDataDocument • Różne sposoby generowania DataSet • Relacja.Nested=True • ColumnMapping=MappingType.Attribute • Transmisja DiffGram • Szybko podejrzeć zawartość DataSet: • myDS.WriteXml( Console.Out ) • Lub: Process.Start("iexplore.exe",@"C:\TMP\tmp.xml");
Demo • Tworzenie DataSet • Dodanie pola • Podstawowe operacje • Klucze, triggery i relacje
Wyszukiwanie/filtrowanie • DataTable.Select(…); DataTable.Find(rPK) • Kilka różnych DataView na jednym DataSet (jednej kopii danych) • Filtry: • Zdarzenie ListChanged dt.DefaultView.RowFilter = ”Pole=‘Wartość’” dt.DefaultView.RowFilter = ”InvData=#mm/dd/yyyy#” dt.DefaultView.RowFilter = ”Parent.InvData=#mm/dd/yyyy#”
DataView i wyszukiwanie • Jeżeli szukamy nie wg PK, lepiej DataView • Warto posortować wg. często filtrowanych pól • DataView buduje wtedy INDEX • Lepiej: v.Sort="Name”; v.FindRows(” KOPACZ”); • Tworzenie DataView: DataView v = new DataView(customerTable,"City='Warszawa'","Name, Surname DESC",DataViewRowState.OriginalRows ); v.FindRows(new object [] {„pole1”,”pole2”});
DataView i relacje • DataView „budowany” na tabeli nadrzędnej • Operatory • Parent(NazwaRelacji).Pole • Child(NazwaRelacji).Pole • Avg,Sum,Max, itp DataRelation rel = ds.Relations.Add("TestRel",…); DataView view = new DataView(ds.Invoice, "Sum(Child(TestRel).value)>=600", "", DataViewRowState.CurrentRows);
Demo - wyszukiwanie • Stworzenie DataView • Bazowanie na tabelach • Zabawy z wyrażeniami • Bez XML
DataSet a „reszta świata” Czyli DataSet i baza danych
Podstawa to DataAdapter • DataAdapter <-> baza • SelectCommand • CommandBuilder • InsertCommand, UpdateCommand, DeleteCommand, • DataAdapter <-> DataSet • MissingSchemaAction/MissingMappingAction • TableMappings.Add (tabela_bd,tabela_ds) • ColumnMappings.Add (bd,ds) • Jeden DataAdapter do aktualizacji jednej tabeli • DataAdapter decyduje ile danych znajdzie się w DataSet
Szybko wygenerować DataSet • DataAdapter może wygenerować DataSet • Nazwy kolumn prawidłowe • Tabele – Table,Table1… • da.Update(ds,”Table1”) • ds.WriteXmlSchema(…) • XSD.EXE SqlCommand sql=new SqlCommand("select * from Customer; select * from Invoice",sqlConnection1); SqlDataAdapter da=new SqlDataAdapter(sql); DataSet ds=new DataSet(); …Mapowania da.FillSchema(ds); da.Fill(ds)
Jak (nie) budować dynamicznego kodu i filtrować • SP z odpowiednimi parametrami (NULL – nie filtruj) • Dynamiczna budowa • UŻYWAĆ StringBuilder • Sprawdzać parametry (SQL Injection) • „where = ?” ALTER PROCEDURE GetCustomers ( @City NVARCHAR(15) … )AS select * from Customers where (City=@City or @City is null) AND … select * from Customers where City=COALESCE(@City, City)AND …
Stronicowanie… • Znaleźć coś co „wyznacza” strony • Specjalne wyrażenie SELECT… SELECT TOP <LiczbaWierszyNaStronie> InvoiceID,Client,City… FROM Invoices WHERE InvoiceID NOT IN (SELECT TOP <LiczbaWierszyDoPominięcia> InvoiceID FROM InvoicesORDER BY Client, City) ORDER BY Client, City
Aktualizacja • IDataAdapter • Bazuje na wersjach wiersza • Dodane -> InsertCommand • Zmienione -> UpdateCommand • Usunięte -> DeleteCommand • Generowanie • Przy użyciu CommandBuilder • Wystarczająco proste SelectCommand… • Ręcznie da.Update(ds,”Customer”); … da1.Update(ds.GetChanges(DataRowState.Deleted));
Problem – konflikt aktualizacji • 3 wersje DataRowVersion • Original, Current, Proposed, • Default • Wszystko zależy od …Command • Porównanie wszystkich wartości • Timestamp • Wcale? • 5 wersji DataRowState • Added,Deleted,Modified,Unchanged • Detached
Demo - Mapowanie + aktualizacje • DataSet wypełniany z SP • Kilka wyników z SP i generowanie automatyczne DataSet • Konflikt
Databinding Czyli związywanie „czegoś” z „czymś”
DataBinding • Głównie zastosowanie w prezentacji danych • Pola związane relacjami • Praktycznie - dowolna właściwość R/W do dowolnej właściwości
Składnia – Windows Forms • „Proste związywanie” • „Złożone związywanie” (complex binding) • Związywanie z listą wartości (np. ListBox) wyboru • DataSource/DisplayMember/ValueMember • SelectedValue • CurrencyManager dla danego DataSource NazwaKontrolki.DataBindings. Add(„Właściwość”,źródło,”element”) Form1.BindingContext[MójDataset].Position -=1
Składnia – ASP.NET • Podstawowa różnica • Związywanie z kopią! (stąd -> kontrolka.DataBind()) • Proste • Złożone • DataSource, DataTextField, DataTextFormatString, DataValueField • IDataReader <asp:TextBox id=„TextBox1” text=‘<%# tbl.Rows[0][„Kolumna”] %> SqlCommand cmd=sqlconnection1.CreateCommand(); cmd.CommandText=„select id,name from Customer”; SqlDataReader rdr=cmd.ExecuteReader(); lstBox.DataSource = rdr; lstBox.DataTextField = „name”; lstBox.DataValueField = „id”; lstBox.DataBind();
Demo – binding i okolice • Manipulacja wersjami pól • Jak się zmieniają • AcceptChanges • Formatka master-detail • Update wielopoziomowy w transakcji • Przyciski poprzedni/następny • DataBinding pomiędzy CheckBox a Enabled Panel-u
Część II – administracja MSDE Ograniczenia Instalacja Zarządzanie
Kilka słów o ograniczeniach • MSDE: • Do 2 GB RAM; max 2 procesory (HT) • 8 średniej złożoności zapytań (workload governor) • Tylko dla aktywnych połączeń • Ograniczenie działa dla danej instancji • 16 równoległych instancji (nazwanych) • Dane w bazie maks 2 GB; log nie jest ograniczony • Brak Analysis Services i Full Text Search • Nie publikuje dla replikacji transakcyjnej • Replikacja MERGE – tylko węzeł podrzędny • Projektowanie bazy: • VS.NET; VISIO; Access • OSQL jak ktoś lubi
Sposoby instalacji • Wykorzystanie MSM • Ale – wtedy też my musimy sami dystrybuować poprawki! • HotFix powinny działać… • Wywoływanie pliku SETUP.EXE • Parametry: • /Q – o nic nie pyta • /INSTANCENAME=„mojainstancja„ • /SECURITYMODE=SQL • /SAPWD = “moje tajne hasło” • /COLLATION=„nazwa” • Plik MSI dodany do własnej instalacji i uruchamiany jako etap • Uwagi o SP3a (parametry w linii poleceń) • /DISABLENETWORKPROTOCOLS=0 – nie nasłuchuje na żadnych portach (tylko lokalnie); domyślna opcja
Dystrybucja własnego schematu danych • Plik LDF i MDF • Skrypty • Jeden niewygodny • Kilka: • Tworzenie tabel • Ładowanie danych • Tworzenie więzów • Tworzenie widoków, SP, funkcji • Prawa dostępu
Kilka opcji w bazie • Po „CREATE DATABASE” exec sp_dboption N'DD2003', N'autoclose', N‘true' exec sp_dboption N'DD2003', N'trunc. log', N'true' exec sp_dboption N'DD2003', N'autoshrink', N'true' exec sp_dboption N'DD2003', N'auto create statistics', N'true' exec sp_dboption N'DD2003', N'auto update statistics', N'true'
Podstawowe operacje administracyjne • SQLDMO/TSQL (też – DTS) • Warto przeczytać Sql Server Books Online • Kopia i odzyskiwanie danych • BACKUP DATABASE DD2003 TO DISK='C:\T1‘ • RESTORE DATABASE DD2003 FROM DISK='C:\T1‘ • Dołączanie/odłączanie bazy • sp_attach_db/sp_detach_db • DBCC CHECKDB('DD2003') • Zastępuje DBCC CHECKALLOC w SQL 7.0 • sp_addlogin/ sp_adduser/sp_addrolemember
Część końcowa Uwagi o projekcie, wydajności…
Kilka uwaga o wydajności • Klucz główny • Autoincrement? • GUID ! (uniqueidentifier/ klasa Guid ) • Kilka wyników w przy jednym zapytaniu • CommandBehavior (IDataReader) • KeyInfo – brak blokad • SingleResult • SingleRow • Schemat bazy • Zamiast wartości NULL – dodatkowy wiersz „puste” • Bez PK/więzów…
DataSet a obiekty „logiki „biznesowej • Wzorce projektowe • Microsoft Data Patternshttp://msdn.microsoft.com/practices/type/Patterns/data • Data Access Application Block • Narzędzia do mapowania O/R • LLBLGen PRO • SQL Server Centric .NET Code Generator (OlyMars) • Oparty o wzorce • Gotowe (prawie) • Komponenty biznesowe, TreeView Factory, Usługi Web, Styl Object Space • BETA! • http://www.microsoft.com/france/msdn/olymars
Podsumowanie • IConnection – pula • Nie trzymać „na zaś” • DataSet – potężny, wersje wartości • Wyszukiwanie, XML • IDataReader – bałagan, ale szybki • IDataAdapter – od niego zależy komunikacja z bazą • DataBinding – doskonałe nie tylko do prezentacji danych • MSDE – wygodna baza, którą łatwo można uaktualnić do pełnego SQL w razie potrzeby • Trochę pracy w oprogramowaniu części administracyjnej • MS Access? • Ale warto – w porównaniu z MDB to zupełnie inna klasa rozwiązań
Dziękuję za uwagę • Pytania: • tkopacz@tomaszkopacz.com • Po prezentacji…