ADO.NET połączenie z bazą danych

 

Standardowo powinienem zacząć projekt od projektu bazy danych. Nauczony jednak wcześniejszymi doświadczeniami, że zazwyczaj to co powinno działać bez problemu u mnie akurat nie działa, najpierw postanowiłem sprawdzić czy połączenie do dostępnej bazy zostanie poprawnie nawiązane oraz opisać proces łączenia się z bazą na blogu.

Do ustanowienia połączenia z bazą danych na serwerze należy znać trzy wartości:

  1. nazwę instancji
  2. nazwę bazy danych
  3. sposób autentykacji (niezbyt ładnie brzmi w języku polskim) użytkownika (jeśli będzie to SQL Server Authentication to dodatkowo nazwę użytkownika i hasło)

W moim przypadku będą to odpowiednio: lokalna instancja SQL Server 2008 R2 Express o nazwie SQLEXPRESS, AdventureWorks, tryb Windows Authentication.

Wyposażeni w taką podstawową wiedzę możemy przystąpić do próby nawiązania połączenia z bazą danych, na początek w najprostszy możliwy sposób. Do stworzenia połączenia wykorzystana zostanie technologia ADO.NET.

Na początek niezbędne jest dodanie odpowiednich przestrzenii nazw:

using System.Data;
using System.Data.SqlClient;

Połączenie jest zestawiane poprzez utworzenie i wykorzystanie obiektu klasy SqlConnection, który musi mieć przypisany tzw. connection string. Jest to łańcuch znaków zawierający pary nazwa-wartość, rozgraniczone znakiem średnika. W tym przypadku będzie on miał postać:
string connectionString = @"Data Source=.\SQLEXPRESS;" + 
    "Initial Catalog=AdventureWorks; Integrated Security=True;";

W kodzie tym występują trzy opisane wcześniej składniki niezbędne do ustanowienia połączenia z bazą danych:

  1. Data source – nazwa instancji
  2. Initial Catalog – nazwa bazy danych
  3. Integrated Security – wykorzystanie do logowania Windows Authentication

Odnośnie powyższych ustawień należy objaśnić ponadto znaczenie symboli specjalnych. Pierwszym z nich jest symbol @, który postawiony przed łańcuchem znakowym przekazuje kompilatorowi informację, aby znak \ był interpretowany dokładnie tak jak jest on interpretowany przez człowieka. Oznacza to, że w danym stringu znane wszystkim połączenia, takie jak \n \t nie są przetwarzane przez kompilator. Drugim symbolem, który należy objaśnić jest zastosowanie znaku kropki w ścieżce określającej położenie instancji. Otóż kropka ta oznacza, że dana instancja ma być poszukiwana na maszynie lokalnej.

Najprostsze połączenie do bazy danych, przy wykorzystaniu powyższego connection stringa może być więc wykonane w następujący sposób:

string connectionString = @"Data Source=.\SQLEXPRESS;" + 
    "Initial Catalog=AdventureWorks; Integrated Security=True;";

SqlConnection cn = new SqlConnection(connectionString);
cn.Open();
    //perform operations on a database
cn.Close();

Otworzenie połączenia następuje poprzez wywołanie metody Open na obiekcie klasy SqlConnection. Uwaga: Pamiętać należy, aby po zakończonych operacjach zamykać połączenie poprzez wywołanie metody Close. Wywołanie tej metody na już zamkniętym połączeniu nie powoduje wyrzucenia wyjątku. 

Takie podstawowe rozwiązanie ma dwie zasadnicze wady. Po pierwsze łatwo o pomyłkę we wpisywaniu odpowiednich przełączników odnośnie połączenia, po drugie brak w przedstawionym kodzie odpowiednich zabezpieczeń i dobrych praktyk programistycznych. Spóbujmy zatem nieco poprawić ten kod.

Przede wszystkim ze względów bezpieczeństwa oraz wygody, jaką jest wykorzystanie Intelisense, należy do tworzenia connection stringa wykorzystać obiekt klasy SqlConnectionStringBuilder. Utworzenie obiektu pozwala na wykorzystanie jego właściwości podpowiadanych przez Visual Studio. Utworzenie connection stringa będzie miało zatem następujący odpowiednik kodzie:

SqlConnectionStringBuilder connectionString = new SqlConnectionStringBuilder();
connectionString.DataSource = @".\SQLEXPRESS";
connectionString.InitialCatalog = "AdventureWorks";
connectionString.IntegratedSecurity = true;

Do obsługi połączenia z bazą danych wysoce zalecane jest natomiast wykorzystanie bloku using. W przypadku jego zastosowania zapewnione jest, że w przypadku napotkania na nieoczekiwany wyjątek, zawsze na końcu bloku połączenie z bazą danych zostanie poprawnie zamknięte. Ponadto należy zadbać, aby nie wykonać polecenia open na już otwartym połączeniu. Wykonanie takie spowoduje wyrzucenie wyjątku InvalidOperationException. Błędne dane logowania powodują wyrzucenie wyjątku SqlException.

Połączmy zatem wszystko co zostało opisane w całość. Proponuje następujący kod w ASP.NET wykonywany po kliknięciu w przycisk o nazwie Button1:

protected void Button1_Click(object sender, EventArgs e)
{
    SqlConnectionStringBuilder conString = new SqlConnectionStringBuilder();
    conString.DataSource = @".\SQLEXPRESS";
    conString.InitialCatalog = "AdventureWorks";
    conString.IntegratedSecurity = true;

	//Polecam przeczytanie komentarzy do tego postu
    using(SqlConnection cn = new SqlConnection(conString.ConnectionString))
    {
        try
        {
            cn.Open();
            System.Diagnostics.Debug.WriteLine("Connection established");
            System.Diagnostics.Debug.WriteLine("Current state is " + cn.State);
        }        
        catch(InvalidOperationException ex)
        {
            System.Diagnostics.Debug.WriteLine("Connection already opened");
            System.Diagnostics.Debug.WriteLine("Current state is " + cn.State);
        }
        catch(SqlException ex)
        {
            System.Diagnostics.Debug.WriteLine("Connection failed because of: " + ex.Message);
            System.Diagnostics.Debug.WriteLine("Current state is " + cn.State);
        }
        catch(Exception ex)
        {
            System.Diagnostics.Debug.WriteLine("General Exception: " + ex.Message);
        }
    
        cn.Close();
    }

}

W kodzie wykorzystana została nieopisana wcześniej właściwość obiektu cn klasy SqlConnection. Jest nią State. Właściwość ta przyjmować może wartości wyliczeniowe znajdujące się w klasie statycznej ConnectionState. Najbardziej interesujące z punktu widzenia przedstawionego kodu są w tym momencie wartości Open oraz Closed.

Wykonanie tego kodu spowoduje wypisanie:

Connection established

Current state is Open

Oznacza to, że połączenie z bazą danych nawiązane zostało poprawnie. Sprawdźmy co się stanie, gdy podane zostaną niepoprawne dane logowania, czyli np. zmienimy nazwę bazy danych:

//was: conString.InitialCatalog = "AdventureWorks";
conString.InitialCatalog = "AdventureWork";

Taka zamiana w kodzie spowoduje wypisanie:

Connection failed because of: Cannot open database "AdventureWork" requested by the login. The login failed.

Login failed for user ‚nazwa_komputera\Michal’.

Current state is Closed

Przetestujmy na koniec, po przywróceniu poprawnej nazwy bazy danych, wywołanie metody Open na już otwartym połączeniu:

try
{
   cn.Open();
   cn.Open();
   System.Diagnostics.Debug.WriteLine("Connection established");
   System.Diagnostics.Debug.WriteLine("Current state is " + cn.State);
}
...
Wywołanie kodu z tak przeprowadzonymi zmianami spowoduje wypisanie:

A first chance exception of type ‚System.InvalidOperationException’ occurred in System.Data.dll

Connection already opened

Current state is Open

Przedstawiony tok rozumowania pozwala na stwierdzenie, że połączenie do bazy danych nawiązywane jest w sposób poprawny. Można więc zatem przystąpić do projektowania bazy danych na potrzeby aplikacji.

Reklamy

4 Responses to ADO.NET połączenie z bazą danych

  1. Gutek says:

    Ql, dawno nie widzialem art na temat ADO.NET, teraz kazdy sie koncentruja na NH i na EF. Wiec inne tematy sa przezemnie mile widziane 🙂

    Warto wspomniec, iz CS mozna zbudowac na wiele sposob i moze miec on wiele postaci. Dla „zapominalskich” takich jak chociazby jak ktory do tej pory nie pamieta CS na pamiec a wykorzystywal go pareset razy (pewne rzeczy po prostu ludziom do glowy nie wchodza ;)) to warto zagladac na strone: http://www.connectionstrings.com/ a taka mala sciagawka 🙂 przydaje sie

    Dodatkowo warto wspomniec iz CS nie tylko z kodu mozna stworzyc, ale mozna go tez utworzyc w APP.Config przez co bedzie latwiej go zmieniach/modyfikowac po tym jak aplikacja zostanie z buildowana i zainstalowana:
    http://msdn.microsoft.com/en-us/library/ms254494.aspx

  2. Przemek Nawrocki says:

    Wartościowy artykuł dla rozpoczynających pracę z programowaniem w ado.net.

    Pozwolę sobie jednak podzielić z moimi uwagami. Dotyczy obiektu conString, który w moim mniemaniu nie jest stringiem a takowy wszak jest potrzebny do SqlConnection.
    Krótko mówiąc SqlConection krzyczy jesli chcemy powolac obiekt SqlConnection(conString).

    chodzi o ten fragment powyższego kodu:
    SqlConnectionStringBuilder conString = new SqlConnectionStringBuilder();
    conString.DataSource = @”.\SQLEXPRESS”;
    conString.InitialCatalog = „AdventureWorks”;
    conString.IntegratedSecurity = true;
    using(SqlConnection cn = new SqlConnection(conString))
    { …itd

    • Przemek Nawrocki says:

      jest :
      using(SqlConnection cn = new SqlConnection(conString))

      winno być:
      using (SqlConnection cn = new SqlConnection(conString.ConnectionString))

      • Oczywiście, że tak 🙂 Miło wiedzieć, że komuś udało się dotrzeć do artykułu, a tym bardziej poświęcić czas na jego przeanalizowanie 🙂 Nie dam sobie teraz ręki uciąć za to, co jest w kodzie, ale błąd najprawdopodobniej wynika z tego, że ja zrobiłem sobie metodę wykonującą całą inicjalizację odpowiadającą za połączenie i zwracałem string, natomiast w momencie pisania na bloga nie chciałem wydlużać kodu i z rozpędu zapomniałem wyciągnąć te dane. Za moment poprawiam kod na blogu i dziękuję za zwrócenie uwagi 🙂

Skomentuj

Wprowadź swoje dane lub kliknij jedną z tych ikon, aby się zalogować:

Logo WordPress.com

Komentujesz korzystając z konta WordPress.com. Log Out / Zmień )

Zdjęcie z Twittera

Komentujesz korzystając z konta Twitter. Log Out / Zmień )

Facebook photo

Komentujesz korzystając z konta Facebook. Log Out / Zmień )

Google+ photo

Komentujesz korzystając z konta Google+. Log Out / Zmień )

Connecting to %s

%d blogerów lubi to: