[Tutorial] Jak sprawić by plik bazy SQL był w folderze app

Ciekawe artykuły dotyczące C#

Moderator: xxSlayeRxx

[Tutorial] Jak sprawić by plik bazy SQL był w folderze app

Sponsor

Sponsor
 

[Tutorial] Jak sprawić by plik bazy SQL był w folderze app

Postprzez SzczwanyLisek » Pn mar 23, 2009 4:27 pm

Witam,
po ciężkich bojach z MS SQL Express i różnymi próbami podpięcia bazy pod aplikacje tak by była ona dostępna dla każdego użytkownika który pobierze aplikację postanowiłem się podzielić wiedzą - How to do...

Wstęp
W tutorialu zakładam, że użytkownik końcowy posiada zainstalowany SQL Server w wersji Express, oraz uruchomioną usługę serwera. Przedstawiony poniżej sposób został sprawdzony dla duetu:
- Microsoft Visual C# 2008 Express
- Microsoft SQL Server 2008 Express

Przygotowania
Wraz z MS SQL Server 2008 Expres dostępna jest aplikacja MS SQL Server Management Studio. Narzędzie to bardzo upraszcza tworzenie bazy danych (poprzez jej wyklikanie). Utworzona baza danych znajduje się w 'X:\Program Files\Microsoft SQL Server\MSSQL10.SQLEXPRESS\MSSQL\DATA' gdzie X to dysk na którym zainstalowano SQL Server.
W normalnym procesie tworzenia aplikacji korzystamy z kompilacji z aktywna opcją Debug build. Gdy już wydaje się, że wszystko jest wporządku przechodzimy do Release Build.
Pora podzielić się aplikacją innymi...

Problem
Program śmiga, release build odpalony, to czas skopiować zawartość folderu Release na pena i pochwalić się programem koledze. Uruchamiamy program u kolegi i...
Wystąpił problem z aplikacją MojaAplikacja i zostanie ona zamknięta. Przepraszamy za kłopoty.

Hmm i o co chodzi ?? Niby wszystko ok, plik z baza w folderze aplikacji, usługa SQL Server odpalona a mimo to nie działa. Otóż chodzi o wiele rzeczy, ale po kolei...

Rozwiązanie
1) W aplikacji MS SQL Server Management Studio należy ustawić w Properties serwera -> zakładka Security -> Server authentication na SQL Server and Windows Authentication Mode (domyślnie ustawione jest Windows Authentication Mode).
2) W kodzie źródłowym swojej aplikacji odnaleźć connection string, w moim przypadku wygląda on tak:
Kod: Zaznacz cały
Baza = @"Data Source=(local)\SQLEXPRESS;User ID=sa;password=TwojeHaslo;Database=nazwaBazy;Trusted_Connection=Yes;";

Data Source - zrodlo danych, w tym przypadku serwer lokalny. Odwoluje się do instancji SQLEXPRESS. Instancji do których można się podłączyć może być więcej, najprostszym sposobem by sprawdzić jakie są dostępne w systemie to odpalenie aplikacji SQL Server Configuration Manager. Domyślnie podczas instalacji MS SQL Server Express tworzona jest instancja SQLEXPRESS i można spokojnie się do niej odwoływać.
User ID - wybieram super użytkownika (pominąć jeśli nie jest znane hasło dla 'sa')
password - haslo uzytkownika (pominąć jeśli nie jest znane hasło dla 'sa')
Database - nazwa bazy danych
Trusted_Connection - wymagane dla Windows integrated security
W sieci jest kilka stron opisujących najpopularniejsze connection stringi - zachęcam do lektury.
3) Próba połączenia przy braku założonej bazy danych ( nie mylić z brakiem pliku bazy) skutkuje się pojawieniem odpowiedniego błędu który został przytoczony wyżej. Na etapie kompilacji dostaniemy wprost informacje co jest nie tak - ano próbujemy się odwołać do nieistniejącej bazy danych. Sprawdźmy więc czy baza istnieje, jeśli jej niema należy ją utworzyć lub zaimportować.
Do stworzenia bazy danych wykorzystałem MS SQL Management Studio, więc nie będę tracił czasu na wpisywanie ręcznie w kodzie instrukcji do stworzenia bazy, tabel, pól,..., a zaimportuję przygotowaną wcześniej bazę.
4) Wygodnie do dalszych celów jest stworzyć metodę która zajmie się sprawdzaniem czy baza jest czy jej niema.
Kod: Zaznacz cały
private string polaczenie()
{
            string Baza;
            Server selectedServer = new Server(".\\SQLEXPRESS");
            foreach (Database db in selectedServer.Databases)
            {
                if (db.Name == "nazwaBazy")
                {                   
                    MessageBox.Show("BAZA ISTNIEJE");
                }
                else
                {
                    //importuje bazę danych
                    string plikBazy = Application.StartupPath+"\\nazwaBazyDB.mdf";                   
                    string queryString = String.Format("CREATE DATABASE nazwaBazy ON PRIMARY (FILENAME = '{0}') FOR ATTACH",plikBazy);
                   
                    StringBuilder errorMessages = new StringBuilder();
                    using (SqlConnection connection = new SqlConnection(@"Data Source=(local)\SQLEXPRESS;User ID=sa;password=MojeHaslo;Trusted_Connection=Yes;"))
                    {
                        SqlCommand command = new SqlCommand(queryString, connection);
                        try
                        {
                            command.Connection.Open();
                            command.ExecuteNonQuery();
                        }
                        catch (SqlException ex)
                        {
                           for (int i = 0; i < ex.Errors.Count; i++)
                            {
                                errorMessages.Append("Index #" + i + "\n" +
                                    "Message: " + ex.Errors[i].Message + "\n" +
                                    "Linia: " + ex.Errors[i].LineNumber + "\n" +
                                    "Zrodlo: " + ex.Errors[i].Source + "\n" +
                                    "Procedura: " + ex.Errors[i].Procedure + "\n");
                            }
                            MessageBox.Show(errorMessages.ToString());
                        }
                    }
                }
            }
            Baza = @"Data Source=(local)\SQLEXPRESS;User ID=sa;password=MojeHaslo;Database=nazwaBazy;Trusted_Connection=Yes;";
            return Baza;
}

Krótki komentarz:
Server selectedServer = new Server(".\\SQLEXPRESS"); - lokalny serwer i jego instancja
foreach(...) - dla każdej istniejącej bazy wykonuje sprawdzenie 'czy jest tu moja baza'
Gdy baza nie istnieje importuję ją z pliku (szerzej na http://msdn.microsoft.com/en-us/library/aa258257.aspx).
Fragment z przechwytywaniem wyjątku można śmiało zakomentować, jednak dla celów tego tutoriala zdecydowałem się go zostawić.

Podsumowanie
Tak przygotowana aplikacja, nie powinna sprawiać problemów przy przenoszeniu jej na inne maszyny. Przedstawioną funkcję można poprawić tak by po napotkaniu pożądanej bazy w systemie przerywała ona swoje działanie. Jak widać nie jest ona oszczędna w czasie - przelatuje x razy przez wszystkie bazy i dla każdej bazy której nazwa jest inna od 'nazwaBazy' próbuje zaimportować bazę.
Mam nadzieję, że przedstawiony tu sposób pomoże komuś w szybszym uporaniu się z problemem jaki napotkałem.
Informatyk - pomyślała studentka. Studentka - pomyślał bezdomny.
SzczwanyLisek
Member
 
Posty: 58
Dołączył(a): Śr mar 11, 2009 9:40 pm
Lokalizacja: Gliwice/Tarnowskie Góry

Re: [Tutorial] Jak sprawić by plik bazy SQL był w folderze app

Postprzez mykhaylo » Pn mar 23, 2009 5:16 pm

Bardzo fajnie, że ktoś w końcu zdecydował się napisać rozwiązanie do swojego problemu. Przyznam szczerze że nie wszystko zrozumiałem co i jak, ale na pewno gdybym miał jakiś podobny problem, to spróbowałbym tego rozwiązania.
Za odwagę i w miarę opisane rozwiązanie duży plus. Mały minus za lekkie uproszczenie opisu rozwiązania.
Avatar użytkownika
mykhaylo
Member
 
Posty: 1475
Dołączył(a): Pn cze 09, 2008 5:53 pm
Lokalizacja: Warszawa

Re: [Tutorial] Jak sprawić by plik bazy SQL był w folderze app

Postprzez Mikoj » Pn mar 23, 2009 7:34 pm

++++++++ za chęci i fajnie nawet wyszło i fajny przykład pokazałeś forumowiczom ze można coś od siebie dać (wiedza) Bardzo mi się podoba taki sposób rozwiązywania problemów przez samego problemonadawce :)
Będzie Lepiej...
Avatar użytkownika
Mikoj
Member
 
Posty: 220
Dołączył(a): N maja 06, 2007 12:06 pm
Lokalizacja: Kraków

Re: [Tutorial] Jak sprawić by plik bazy SQL był w folderze app

Postprzez Hellraider » Cz mar 26, 2009 10:52 am

Witam.

Pętlę foreach wyszukującą bazę danych o podanej nazwie można zastąpić taką oto konstrukcją:

Kod: Zaznacz cały
 Database database = selectedServer.Databases.OfType<Database>().FirstOrDefault(db =>
                    {
                          return db.Name.Equals("nazwaBazy");
                    });
         if (database != null) { ....} else {....}


Metoda OfType() określa jakiego typu dane będziemy poszukiwać w kolekcji.
Metoda FirstOrDefault() "wyciąga" z kolekcji pierwszy napotkany obiekt zgodny z warunkiem podanym w swoim parametrze, jeśli nie napotka żadnego zwraca null.

Pozdrawiam.
Hellraider
Member
 
Posty: 83
Dołączył(a): Pt sie 31, 2007 6:29 pm
Lokalizacja: Warszawa

Re: [Tutorial] Jak sprawić by plik bazy SQL był w folderze app

Sponsors

Sponsor
 


Powrót do Artykuły

Kto przegląda forum

Użytkownicy przeglądający ten dział: Brak zidentyfikowanych użytkowników i 1 gość