70-562: Using the ADO.NET Connected Classes

Artykuł pochodzi w serii przygotowań do egzaminu 70-562 ASP.NET.

Witam w dzisiejszym artykule, w którym mowa będzie o dostępie do danych za pomocą klas, które wymagają aktywnego połączenia.

Używanie wbudowanych klas do operowania na danych

Klasy, za pomocą których możemy dodawać, edytować, usuwać itd. dane dostarczone są razem z frameworkiem .NET.
W sklad .NET’u wchodzą dostawcy do danych tacy jak: OleDb, Odbc, SQLServer, Oracl.
Poniższa tabela pokazuję listę podstawowych klas w ADO .NET. W tabeli pokazane zostały klasy bazowe, klasy klienckie oraz interfejsy:
 image

Podstawowe informacje o obiekcie DbConnection

Klasa DbConnection jest klasą abstrakcyjną, po której klasy połączenia, specyficzne dla dostawcy, dziedziczą. Poniżej hierarchia klas:
image

Oraz przykładowy kod, w którym operujemy na obiekcie DbConnection:

   1: DbConnection connection = new SqlConnection();
   2: connection.ConnectionString = "Server=.;Database=pubs;Trusted_Connection=true";
   3: connection.Open();
   4: //jakaś akcja
   5: connection.Close();

Widzimy utworzenie obiektu DbConnection a następnie wykorzystanie metody ConnectionString, która trzyma ścieżkę do naszej bazy danych. Musimy pamiętać, aby otworzyć połączenie zanim wykonamy jakiekolwiek komendy na bazie. Następnie należy połączenie zamknąć :) Możemy to zrobić za pomocą metody Close lub Dispose.

Konfigurowanie Connection String dla ODBC

Odbc jest jedną ze starszych technologii, które wspiera .NET. Poniżej najczęstsze ustawienia connection stringa dla ODBC:
Driver – sterownik ODBC dla połączenia
DSN – nazwa źródła danych, które mogą być konfigurowane przez administratora
Server – nazwa serwera, do którego się łączymy
Trusted_Connection – opis zabezpieczeń
Database – baza danych, do której się łączymy
DBQ - Zazwyczaj fizyczna ścieżka do źródła danych

Konfigurowanie Connection String dla OleDB

Podobnie jak wyżej, najczęstsze ustawienia:
 Data source - Nazwa bazy danych lub fizycznej lokalizacji pliku bazy danych
 File Name - Fizyczna lokalizacja pliku, który zawiera prawdziwy connection string.
Provider – specyficzny sterownik używający connection stringa do łączenia się danymi

Konfigurowanie Connection String dla SQL Server

Training kit przy opisywaniu connection stringa dla SQL Server wymienił bardzo dużo opcji (2,5 strony A4 :D ). Przedstawię kilka z nich:
 Data Source, addr, address, network address, server - Nazwę lub adres IP serwera bazy danych.
Initial Catalog, database – nazwa bazy danych, z której korzystamy
User ID, uid, user – nazwa użytkownika wykorzystywana do łączenia się z SQL Serverem.
 Password, pwd – hasło potrzebne do połączenia się z serwerem.
Workstation ID, wsid - Nazwa komputera klienckiego, który łączy się SQL Server.

Poza powyższymi są jeszcze między innymi: Current Language, language, Application Name, app, Packet Size, Network Library, net, network, Load Balance Timeout, connection lifetime i wiele innych. Zachęcam do doczytania na MSDN.

Dołączanie lokalnego pliku SQL do SQL EXPRESS

Aby dołączyć lokalny plik SQL do SQL Express możemy użyć do tego następującego connection stringa:

   1: Data Source=.\SQLEXPRESS;
   2: AttachDbFilename=C:\MyApplication\PUBS.MDF;
   3: Integrated Security=True;
   4: User Instance=True

 

Ustawiliśmy Data Source na SQL EXPRESS czyli tak jak chcieliśmy oraz w AttachDbFilename wskazaliśmy plik, który chcemy dołączyć.
W praktyce używa się zazwyczaj konfiguratora wbudowanego w SQL Express, który za nas wygeneruje odpowiedni connection string :)

Używanie connection string w Web Configu

Możemy używać connection stringów w pliku konfiguracyjnym www. Dzięki temu w jednym miejscu mamy kontrolę nad połączeniami do bazy co zapewnia łatwiejsze wprowadzanie zmian. Connection stringi możemy umieścić w znaczniku <connectionStrings> tak jak poniżej:

   1: <connectionStrings>
   2: <add name="PubsData" providerName="System.Data.SqlClient"
   3: connectionString="Data Source=.\SQLEXPRESS;
   4: AttachDbFilename=|DataDirectory|PUBS.MDF;
   5: Integrated Security=True; User Instance=True"/>
   6: </connectionStrings>

 

Powyższy przykład dodaje nowy connection string oraz nadaje mu nazwę PubsData. Do powyższego connection stringa możemy się dostać za pomocą klasy ConfigurationManager, tak jak w poniższym przykładzie:

   1: ConnectionStringSettings pubs = 
   2:        ConfigurationManager.ConnectionStrings["PubsData"];
   3: DbConnection connection = new SqlConnection(pubs.ConnectionString);

 

Korzystanie z Visual Studio w celu dodania nowego połączenia

Dzięki Visual Studio dodawanie nowego połączenia do danych staje się prostsze :) Możemy dodać nowe połączenie używając explorera. Otworzy nam się ładny kreator i będziemy mogli określić co chcemy zrobić. Poniżej server explorer po dodaniu nowej bazy danych. Wystarczy kliknąć na explorerze prawym przyciskiem i wybrać dodanie nowego połączenia:

image

Szyfrowanie connection stringa

Często nasze connection stringi zawierają użytkownika i hasło bazy danych. Na szęście z pomocą przychodzi nam narzędzie Aspnet_regiis.exe, dzięki któremu możemy zaszyfrować ważne dane :)
Możemy szyfrować i deszyfrować zawartość pliku Web.config przy użyciu System.Configuration. DPAPIProtectedConfigurationProvider, który korzysta z ochrony danych Windows API (DPAPI)  lub System.Configuration.RSAProtectedConfiguration- Usługodawcy, który wykorzystuje Rivest-Shamir-Adleman (RSA).
Kiedy trzeba korzystać z tego samego zaszyfrowanego pliku konfiguracji na wielu komputerach w sieci Web, należy użyć System.Configuration.RSAProtectedConfigurationProvider, który pozwala na eksport kluczy do szyfrowania danych. Klucze szyfrujące mogą być importowane do innego serwera. Jest to ustawienie domyślne. Typowy plik Web.config może wyglądać tak:

   1: <?xml version="1.0"?>
   2:   <configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
   3:    <appSettings/>
   4: <connectionStrings>
   5:  <add name="ConnectionString" 
   6:    connectionString="Data Source=.\SQLEXPRESS;
   7:    AttachDbFilename=|DataDirectory|\northwnd.mdf;
   8:    Integrated Security=True;User Instance=True"
   9:    providerName="System.Data.SqlClient" />
  10: </connectionStrings>
  11: <system.web>
  12: ...
  13: </system.web>
  14: </configuration>

 

Element connectionStrings może być zaszyfrowany, jeśli uruchomimy polecenie (w konsoli Visual Studio)
z podaniem pełnej ścieżki do witryny sieci Web np:

   1: aspnet_regiis -pef "connectionStrings" "C:\...\EncryptWebSite"

Po wykonaniu polecenia nasz web config może wyglądać tak:

   1: <?xml version="1.0"?>
   2: <configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
   3: <protectedData>
   4: <protectedDataSections>
   5: <add name="connectionStrings"
   6:   provider="RsaProtectedConfigurationProvider"
   7:   inheritedByChildren="false" />
   8: </protectedDataSections>
   9: </protectedData>
  10: <appSettings/>
  11: <connectionStrings>
  12: <EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Element"
  13:    xmlns="http://www.w3.org/2001/04/xmlenc#">
  14: <EncryptionMethod
  15:    Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc" />
  16: <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
  17: <EncryptedKey Recipient=""
  18:    xmlns="http://www.w3.org/2001/04/xmlenc#">
  19: <EncryptionMethod
  20:    Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5" />
  21: <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
  22: <KeyName>Rsa Key</KeyName>
  23: </KeyInfo>
  24: <CipherData>
  25: <CipherValue>PPWA1TkWxs2i698Dj07iLUberpFYIj6wBhbmqfmNK/plarau4i1k+xq5bZzB4VJW8
  26:    OkhwzcIIdZIXff6INJ1wlZz76ZV1DIbRzbH71t6d/L/qJtuOexXxTi2LrepreK/q3svMLpsJycnDPa
  27:    t9xaGoaLq4Cg3P19Z1J6HquFILeo=</CipherValue>
  28: </CipherData>
  29: </EncryptedKey>
  30: </KeyInfo>
  31: <CipherData>
  32: <CipherValue>Q1re8ntDDv7/dHsvWbnIKdZF6COA1y3S91hmnhUN3nxYfrjSc7FrjEVyJfJhl5EDX
  33:    4kXd8ukAjrqwuBNnQbsh1PAXNFDflzB4FF+jyPKP/jm1Q9mDnmiq+NCuo3KpKj8F4vcHbcj+f3GYqq
  34:    B4pYbblAvYnjPyPrrPmxLNT9KDtDr8pDbtGnKqAfcMnQPvA8l5w3BzPM4a73Vtt2kL/z9QJRu3Svd9
  35:    33taxOO/HufRJEnE2/hcBq30WcBmEuXx3LFNjV+xVmuebrInhhxQgM2froBKYxgjwWiWNjIIjIeTI2
  36:    FQ8nZ8V8kzAVohmDYkZpCj4NQGdrjD996h97phI6NnHZYZHJ7oPRz</CipherValue>
  37: </CipherData>
  38: </EncryptedData>
  39: </connectionStrings>
  40: <system.web>
  41: ...
  42: </system.web>
  43: </configuration>

 

Do deszyfrowania możemy użyć poniższego polecenia:

   1: aspnet_regiis -pdf "connectionStrings" "C:\...\EncryptWebSite"

Korzystanie z obiektu DbCommand

DbCommand używamy do przesyłania jednej lub więcej zapytań pisanych w SQL. Może on być jednym z poniższych typów:
 Data Manipulation Language (DML) - Polecenia pobrania, wstawiania, aktualizowania lub usuwania danych
Data Definition Language (DDL) - Polecenia tworzenia tabel i innych obiektów bazy danych lub modyfikacji  schematu bazy danych.
Data Control Language (DCL) - Polecenia, które nadają, blokują, lub cofają uprawnienia

Poniższy kod pokazuje jak utworzyć i zainicjować (ale nie wykonać) DbCommand:

   1: //pobieramy connection stringa
   2: ConnectionStringSettings pubs =
   3: ConfigurationManager.ConnectionStrings["PubsData"];
   4:  
   5: DbConnection connection =
   6:  new SqlConnection(pubs.ConnectionString);
   7: //tworzymy obiekt DbCommand
   8: DbCommand cmd = connection.CreateCommand();
   9:  cmd.CommandType = CommandType.StoredProcedure;
  10:  cmd.CommandText = "uspGetCustomerById";


Ten kod tworzy obiekt SqlConnection i przypisuje go do zmiennej połączenia, która ma typ danych DbConnection. Obiekt DbConnection jest następnie wykorzystywane do tworzenia SqlCommand, który jest przypisany do zmiennej cmd. DbConnection musi być otwarty przed wywołaniem komendy. CommandText zawiera nazwę procedury przechowywanej, a CommandType wskazuje, że jest to nawiązanie do procedury składowanej.

Używanie obiektu DbParameter do przekazywania danych

Gdy zachodzi konieczność przekazania danych do procedury składowanej, należy używać obiektów DbParameter. Na przykład zdefiniowana przez użytkownika procedura składowana o nazwie uspGetCustomerById  może wymagać ID klienta w celu pobrania odpowiednich klientów. Możemy tworzyć obiekty DbParameter za pomocą Parameters.Add tak, jak poniżej:

   1: ConnectionStringSettings pubs =
   2:   ConfigurationManager.ConnectionStrings["PubsData"];
   3:  
   4: DbConnection connection =
   5:   new SqlConnection(pubs.ConnectionString);
   6: DbCommand cmd = connection.CreateCommand();
   7:  cmd.CommandType = CommandType.StoredProcedure;
   8:  cmd.CommandText = "uspGetCustomerById";
   9:  
  10: DbParameter parm = cmd.CreateParameter();
  11:  parm.ParameterName = "@Id";
  12:  parm.Value = "AROUT";
  13:  cmd.Parameters.Add(parm);

 

Używanie metody ExecuteScalar

Można wykonać zapytanie, które ma zwrócić wynik tabeli zawierającej jeden wiersz i kolumnę, takie jak kwerendy, która np. pobiera całkowitą sprzedaż z danego dzinia. W takich sytuacjach, wyniki mogą być traktowane jako jedna wartość. Na przykład, następująca instrukcja SQL zwraca wynik, który składa się z pojedynczego wiersza w jednej kolumnie:

   1: SELECT COUNT(*) FROM Sales

Poniższy kod pokazuje, jak korzystać z metody ExecuteScalar  i łatwo pobrać ilość wierszy w tabeli Sprzedaż w zmiennej o nazwie count:

   1: ConnectionStringSettings pubs =
   2:  ConfigurationManager.ConnectionStrings["PubsData"];
   3:  
   4: DbConnection connection = new SqlConnection(pubs.ConnectionString);
   5:  
   6: DbCommand cmd = connection.CreateCommand();
   7:  cmd.CommandType = CommandType.Text;
   8:  cmd.CommandText = "SELECT COUNT(*) FROM Sales";
   9:  
  10: connection.Open();
  11: int count = (int)cmd.ExecuteScalar();
  12: connection.Close();

Używanie obiektu DbDataReader

Obiekt DbDataReader dostarcza metody wysokiej wydajności do pobierania danych z magazynu danych. Dostarcza dane tylko do odczytu itp. co sprawia, że jest idealny do wypełniania kontrolek ListBox, DropDownList czy nawet GridView, które mają dane tylko do odczytu.
DbDataReader zawiera metodę Read, która pobiera dane do swojego bufora. Tylko jeden
wiersz danych jest zawsze dostępny w danym czasie. Poniższy kod wykorzystuje metodę Load obiektu DataTable w celu wypełnienia DataTable bezpośrednio z obiektu DataReader połączonego z bazą danych:

   1: ConnectionStringSettings pubs =
   2:   ConfigurationManager.ConnectionStrings["PubsData"];
   3: DbConnection connection = new SqlConnection(pubs.ConnectionString);
   4:  
   5: DbCommand cmd = connection.CreateCommand();
   6:  cmd.CommandType = CommandType.Text;
   7:  cmd.CommandText = "SELECT pub_id, pub_name FROM Publishers";
   8:  connection.Open();
   9:    DbDataReader rdr = cmd.ExecuteReader();
  10:    DataTable publishers = new DataTable();
  11:    publishers.Load(rdr, LoadOption.Upsert);
  12:  connection.Close();
  13:  
  14: GridView1.DataSource = publishers;
  15: GridView1.DataBind();

Korzystanie z DbDataAdapter

DbDataAdapter wykorzystywany jest do przetwarzania i aktualizowania danych pomiędzy DataTable i magazynem danych. Poniżej hierarchia:
image

DbDataAdapter posiada właściwość SelectCommand używaną podczas pobierania danych. SelectCommand musi zawierać prawidłowy obiekt DbCommand, który musi mieć ważne połączenie.

Korzystanie z metody Fill

Metoda Fill przenosi dane z magazynu danych do obiektu DataTable, który przekazujesz do tej metody.
Poniższy kod pokazuje jak DataTable mogą być ładowane przy użyciu metody Fill:

   1: ConnectionStringSettings pubs =
   2:  ConfigurationManager.ConnectionStrings["PubsData"];
   3:  
   4: DbConnection connection = new SqlConnection(pubs.ConnectionString);
   5: SqlCommand cmd = (SqlCommand)connection.CreateCommand();
   6:  cmd.CommandType = CommandType.Text;
   7:  cmd.CommandText = "SELECT pub_id, pub_name FROM Publishers";
   8:  
   9: SqlDataAdapter da = new SqlDataAdapter(cmd);
  10:  DataSet pubsDataSet = new DataSet("Pubs");
  11:   da.Fill(pubsDataSet, "publishers");
  12: GridView1.DataSource = pubsDataSet;

Korzystanie z klasy DbProviderFactory

Istnieje wiele powodów do pisania aplikacji, która nie wymaga kodu specyficznego dla dostawcy bazy. Firma może chcieć, np. przejść z programu Microsoft Access do SQL Server itp.
Tu z pomocą przychodzi nam tytułowa klasa. Poniżej hierarchia:
image
Klasy fabryki dostawcy są implementowane jako singletony, Na przykład poniższy kod pokazuje jak utworzyć nowe połączenie za pomocą SqlClientFactory:

   1: //Pobieramy instancję singletonu
   2: DbProviderFactory factory = SqlClientFactory.Instance;
   3: public DbConnection GetProviderConnection()
   4: {
   5:  DbConnection connection = factory.CreateConnection();
   6:   connection.ConnectionString = @"Data Source=.\SQLEXPRESS;"
   7:    + "AttachDbFilename=|DataDirectory|PUBS.MDF;"
   8:    + "Integrated Security=True;User Instance=True";
   9:    return connection;
  10: }

Używanie klasy DbProviderFactories

Aby zapytać o listę dostępnych fabryk, możesz użyć klasy DbProviderFactories. Zawiera ona metodę o nazwie GetFactoryClasses, która zwraca DataTable. Poniżej przykład pokazujący pobranie listy fabryk oraz informacji o nich i przypisanie do grid viewa:

   1: DataTable providersList = null;
   2: providersList = System.Data.Common.DbProviderFactories.GetFactoryClasses();
   3: GridView1.DataSource = providersList;
   4: GridView1.DataBind();

Używanie ADO.NET Transaction Object

Transakcja jest to atomowa jednostka pracy, która musi być wypełniona w całości. Transakcja się powiedzie, jeśli została wykona cała operacja. Transakcji ma cztery podstawowe właściwości: Cząsteczkowość, spójność, izolację i trwałość (tzw. właściwości ACID).
Możemy użyć obiektu DbConnection z metodą BeginTransaction, która tworzy obiekt DbTransaction. Dzięki temu otrzymamy możliwość obsługiwania transakcji. Poniższy kod pokazuje jak to osiągnąć:

   1: ConnectionStringSettings cnSetting = ConfigurationManager.ConnectionStrings["PubsData"];
   2: using (SqlConnection cn = new SqlConnection())
   3: {
   4:  cn.ConnectionString = cnSetting.ConnectionString;
   5:  cn.Open();
   6: using (SqlTransaction tran = cn.BeginTransaction())
   7: {
   8:  try
   9:  {
  10:   //jakis kod
  11: using (SqlCommand cmd = cn.CreateCommand())
  12: {
  13:  cmd.Transaction = tran;
  14:  cmd.CommandText = "UPDATE jobs SET min_lvl=min_lvl * 1.1";
  15:  cmd.ExecuteNonQuery();
  16: }
  17: tran.Commit();
  18: }
  19: catch (Exception xcp)
  20: {
  21:  tran.Rollback();
  22: }
  23: }
  24: }

Używanie LINQ do pracy z danymi

Linq jest to bardzo fajny mechanizm wprowadzony w .NET 3.0, który np. z naszych tabel w bazie danych tworzy obiekty :) Dzięki linq nie tylko możemy się odnosić do baz Sql Serwer ale również XML czy zwykłych obiektów.
Aby zacząć zabawę z linq musimy stworzyć jakąś bazę oraz tabelę w niej. Następnie musimy stworzyć mapowanie bazy. Aby to osiągnąć dodajemy do projektu nowy plik LinqToSql. Następnie z Serwer Explorera przeciągamy nasze tabele na forme. Wygląda to np. tak:
image

Załóżmy, że nasz plik z mapowaniem nazywał się Dane. Dzięki Linq stworzy nam się klasa która nazwana zostanie (w tym wypadku) DaneDataContext. Dzięki niej będziemy mogli odwoływać się do obiektów stworzonych przez LINQ.

Zapytania w linq, tworzenie nowych danych

Aby wyciągnąć dane z tabeli za pomocą linq tworzymy najpierw nowy obiekt DataContext, o którym wspominałem w poprzednim akapicie a następnie za pomocą zapytania podobnego do sql wyciągamy dane. Poniższy przykład pokazuje jak to osiągnąć:

   1: using (var zalacznik = new DaneLinqDataContext())
   2:              
   3:                  var zatwierdz = from zat in zalacznik.Zalaczniks where zat.NewsId == null select zat;
   4:        }

Przykład dodania danych prezentuje się następująco:

   1: using (var DodajNews = new DaneDataContext())
   2:             {
   3:  
   4:                 New news = DodajNews.News.Single(n => n.Id == id);
   5:                 news.Kategoria = int.Parse(KategorieDrop.SelectedValue);
   6:                 news.Tytul = TytulNewsBox.Text;
   7:                 news.SkroconyOpis = SkroconyOpisBox.Text;
   8:                 news.Tresc = PoleWpis.Content;
   9:                 news.Piorytet = int.Parse(PriorytetBox.SelectedValue);
  10:                 news.Waga = int.Parse(WagaBox.SelectedValue);
  11:                 news.DataUtworzenia = DateTime.Now;
  12:                 DodajNews.SubmitChanges();
  13:                          
  14:  
  15:             }

Widzimy, że wystarczy stworzyć nowy obiekt linq a następnie ustawiać właściwości danej klasy i na końcu je zapisać.

 

To wszystko w dzisiejszym artykule. Jak widzicie zakres materiału jest bardzo duży. W samym training kicie było ok 50 stron. Warto poczytać dużo więcej o powyższych zagadnieniach ponieważ przedstawione przeze mnie są tylko podstawowe informację. Nie pisałem również o asynchronicznym dostępnie do danych.
Wybaczcie literówki ale jest już troszkę późno a nie wiem czy jutro zdążę sprawdzić :)

Tagi: , , , , ,

Wstęp do Linq - prezentacja i materiały

Wczoraj odbyła się prezentacja na temat LINQ. Starałem się pokazać podstawy posługiwania się tym bardzo fajnym narzędziem. Tak jak obiecałem wrzucam prezentację oraz kod, który pisałem. Aby poprawnie działało LINQ to SQL musicie stworzyc sobie prostą baze i wrzucić do pliku Mapa.dbml tak jak to robiłem wczoraj. Kod w kilku ważniejszych miejscach pokomentowałem także można go sobie na spokojnie przeanalizować :)

Dzięki za przybycie! :)

Prezentacja:

[slideshare id=2430892&doc=wstpdolinq-091105103753-phpapp01]

 

Materiały :

Linq.rar (126,00 kb)

Tagi: , , ,

Generowanie mapy witryny z bazy danych

  Od jakiegoś czasu tworzymy pewien projekt w ASP. Jako, że z ASP mam do czynienia po raz pierwszy i wciąż się uczę, trafiłem na pewien problem: Jak wygenerować sobie sitemapa na podstawie bazy danych? Trochę poczytałem w necie, ale były tam bardziej skomplikowane rzeczy, które nam były niepotrzebne. W końcu po przejrzeniu kilku pomysłów z CodeProject udało mi się napisać prosty generator, który spełnia swoje zadanie w naszej aplikacji :)

Działanie generatora jest bardzo proste. Pobiera on dane z naszej bazy i na ich podstawie tworzy odpowiedniego XML-a. Do dostępu do danych i generowania pliku używam LINQ.
Na początku tworzymy sobie dwie tabele, tworzymy relację i dodajemy do projektu plik Database.dmbl (Linq to Sql) tak jak poniżej:

model1

W tabeli MainLink trzymam link nadrzędny do tabeli Link.
Ok. Mamy już bazę z linkami teraz czas napisać generator. Tworzymy nową klasę np. CreateMap. Stwórzmy sobie od razu konstruktor, który będzie ustawiał ścieżkę do sitemapa.

			   1: public class CreateMap
			   2:    {
			   3:        private readonly string _path;
			   4:  
			   5:        public CreateMap(string path)
			   6:        {
			   7:            _path = path;
			   8:        }

Teraz tworzymy metodę GenerateXml, w której wygenerujemy naszą mapę.

			   1: public void GenerateXml()
			   2:        {
			   3:            DatabaseDataContext databaseModel = new DatabaseDataContext();
			   4:            
			   5:            var mainLinks = from lGlowne in databaseModel.MainLinks select lGlowne;
			   6:            var mainLinksList = mainLinks.ToList();
			   7:  
			   8:            var links = from pLinki in databaseModel.Links select pLinki;
			   9:            var linksList = links.ToList();

Na początku tworzymy obiekt obsługi bazy, następnie pobieramy dane z naszych tabel i zapisujemy je w kolekcjach. Dalej użyjemy mechanizmu LINQ to XML, za pomocą którego stworzymy strukturę naszego XML-a.

			   1: XElement main = new XElement("siteMap");

Tworzymy element główny. Powyższa linijka kodu sprawi, że w naszym XML-u pojawi się:

			   1: <siteMap>

Następnie tworzymy nasz główny SiteMapNode

			   1: XElement menu = new XElement("siteMapNode", new XAttribute("title", "Menu"),
			   2:                                                    new XAttribute("description", "Menu strony"));


Po tej operacji mamy stworzoną naszą główną kategorię “Menu” w której umieścimy mapę naszej strony. Teraz pozostaje już tylko odpowiednio zapisać w elemencie “menu” dane z bazy.

			   1: foreach(var mLink in mainLinksList)
			   2:             {
			   3:                 XElement link = (new XElement("siteMapNode", new XAttribute("title", mLink.Nazwa),
			   4:                                                  new XAttribute("description", mLink.SzczegolowaNazwa),
			   5:                                                  new XAttribute("url", mLink.Sciezka)));

Najpierw tworzymy sobie Element z tabeli MainLink, pobieramy z bazy i ustawiamy jego nazwę, opis oraz ścieżkę.

			   1: foreach (var uLink in linksList)
			   2:                {
			   3:                    if (mLink.Id == uLink.LinkGlownyId)
			   4:                        link.Add(new XElement("siteMapNode", new XAttribute("title", uLink.Nazwa),
			   5:                                                              new XAttribute("description", uLink.SzczegolowaNazwa),
			   6:                                                              new XAttribute("url", uLink.Sciezka)));
			   7:                    
			   8:                }
			   9:                menu.Add(link);
			  10:            }

Następnie, w kolejnej pętli, przechodzimy po elementach tabeli “Link” sprawdzamy czy Link należy do MainLink i jeśli tak, dodajemy do naszego linka głównego link podrzędny. Ponownie na podstawie danych uzupełniamy element nazwą, opisem i ścieżką. Na samym końcu dodajemy nasz XElement razem z jego pod elementami do naszego głównego SiteMapNode’a.

Teraz pozostało już tylko nasz główny SiteMapNode zapisać do SiteMapa oraz wszystko zapisać do pliku:

			   1: main.Add(menu);
			   2:           main.Save(_path);

Jak widać, za pomocą LINQ możemy bardzo prosto i szybko stworzyć sobie prosty generator mapy naszej strony :)
TUTAJ możecie zobaczyć kod w całości.

 

Tagi: , ,

Eastgroup.pl na facebooku