[Visual 2015 C# Windows Forms] Obsługa lokalnej bazy danych z wykorzystaniem SQLite - językiem początkującego.

W tym miejscu zadajemy pytania na temat języka C#, dzielimy się swoją wiedzą, udzielamy wsparcia, rozwiązujemy problemy programistyczne.
Awatar użytkownika
danielos
Newb
Newb
Posty: 69
Rejestracja: sobota 02 sty 2016, 15:06
Lokalizacja: Pawłowice, Silesia.
Kontaktowanie:

[Visual 2015 C# Windows Forms] Obsługa lokalnej bazy danych z wykorzystaniem SQLite - językiem początkującego.

Postautor: danielos » środa 18 maja 2016, 20:43

Witam.

Tym razem chciałem przedstawić konfigurację i obsługę lokalnej bazy danych z wykorzystaniem biblioteki SQLite.
Zakładam, że już znasz podstawy programowania w C# i obsługę programu Visual Studio 2015 - więc możliwe, że początkującego to nie zainteresuje, ale różnie to jest.

Więc przystępujemy do działania.

:arrow: Przed przystąpieniem do pisania programu, należy najpierw zaimportować i dodać potrzebne biblioteki. Można to zrobić na wiele sposobów. Jednym z nich jest ściągnięcie odpowiednich plików ze strony źródłowej SQLite. Tylko, którą wersję wybrać i jakie pliki? Jest też duże prawdopodobieństwo, że braknie biblioteki SQLite.Interop.dll. Ja natomiast pokażę inny sposób, który w łatwy sposób doda wszystkie potrzebne pliki - poprzez program Visual dzięki pakietom NuGet. Aby tego dokonać należy w eksploratorze projektu kliknąć prawym przyciskiem myszy na odwołania (references) i z menu wybrać "Zarządzaj pakietami NuGet...".

dodanie_nowego_pakietu.jpg

Otworzy nam się nowe okienko w którym mamy możliwość wyboru odpowiedniego pakietu. W tym celu przechodzimy do zakładki Przeglądaj i w polu wyszukiwania wpisujemy SQLite. Po wyszukaniu i wyświetlenie wyników wybieramy pakiet System.Data.SQLite. Po prawej stronie w informacjach dotyczących pakietu naciskami przycisk Zainstaluj, oraz potwierdzamy OK w kolejnym okienku. Wszystkie wymagane składniki pakietu zostaną automatycznie zainstalowane.

wybranie_pakietów.jpg

Należy jeszcze sprawdzić czy kopia lokalna jest tworzona. Przechodzimy do kategorii odwołania w naszym projekcie i rozwijamy je. Znajdować się tam będą między innym odwołania takie jak System.Data.SQLite, System.Data.SQLite.EF6, System.Data.SQLite.Linq. Po zaznaczeniu odpowiedniego odwołania (oczywiście dotyczącego tylko SQLite) w okienku właściwości (Properties) przy opcji kopia lokalna (Copy Local) powinno być ustawione True, jak to pokazano na poniższym zdjęciu:

Ustawienie odwołań.jpg

Dzięki temu ustawieniu w folderze w którym znajduje się nasz plik wykonywalny exe naszego programu zostaną utworzone pliki które są konieczne do prawidłowego działania naszego programu.

Po konfiguracji przechodzimy do programu.

Omówię jedynie fragmenty kodu, które są potrzebne do obsługi bazy danych.

Pod tym adresem można znaleźć przydatne informacje dot. budowania składni zapytań SQL.

Nasz program będzie umożliwiał utworzenie nowej bazy danych, otwarcie istniejącej, oraz dodanie i usunięcie danych, a także wypisanie kolejnych danych, które są zawarte w bazie danych. W projekcie zostaną użyte następujące kontrolki:

  1. Button;
  2. TextBox;
  3. Label

Wyglądać to będzie następująco:

Działający program.jpg

Opiszę jedynie kod odpowiedzialny za obsługę bazy danych. W programie znajduje się dość duża ilość komentarzy opisująca co się w danej chwili dzieje

:idea: Obsługę lokalnej bazy danych można podzielić na kilka czynności:

  1. Utworzenie nowego pliku
  2. Otwarcie/Zamknięcie bazy danych
  3. Wysłanie zapytania, które nie zwraca żadnych danych (np. utworzenie tabeli, dodanie nowych danych)
  4. Wysłanie zapytanie, które zwraca jakiś wynik (np, wyszukanie danych)

W pierwszej kolejności zarejestrujemy przestrzeń nazw naszej biblioteki:

Kod: Zaznacz cały

using System.Data.SQLite;


Aby utworzyć nowy plik naszej bazy należy wywołać funkcję:

Kod: Zaznacz cały

//tworzenie nowego pliku
SQLiteConnection.CreateFile("c:\\nowe_dane.db");


W programie, który przedstawia sposób wykorzystania bazy danych do funkcji przekazywana jest zmienna path, która zawiera lokalizację pliku. Po utworzeniu pliku konieczne jest utworzenie nowej tabeli w bazie danych, ale o tym za chwilę.

Otwarcie pliku wymaga utworzenia najpierw zmiennej, do której przypisany będzie nasz obiekt, czyli plik naszej bazy danych.

Kod: Zaznacz cały

//zmienna przechowująca obiekt bazy danych
SQLiteConnection db_connect;         

//utworzenie obiektu potrzebnego do połączenia się z bazą, składnia wymagana przez bibliotekę.
db_connect = new SQLiteConnection("Data Source =" + path + ";Version=3;");

//połączenie się z bazą danych - funkcja tworząca nowy plik nie powoduje otwarcia go
db_connect.Open();


Następnie tworzymy obiekt, który przypisany jest do wcześniej utworzonej zmiennej. Jako parametr przekazywana jest składnia zawierająca adres naszego pliku, oraz wersję bazy danych. Możliwe jest również przesłanie innych informacji, takich jak np. hasło, ale na chwilę obecną nie zajmowałem się tym. Informacje na temat tej składni można znaleźć pod tym adresem- i nie tylko hasła. W ostatniej linijce poprzez wywołanie funkcji/metody Open() otwierane jest połączenie z bazą danych. Zamknięcie bazy danych wykonuje się w bardzo prosty sposób, poprzez wywołanie metody/funkcji Close().

Kod: Zaznacz cały

//zamknięcie połączenia z bazą danych
db_connect.Close();


Warto tutaj wspomnieć, że w przypadku, gdy plik pod wskazanym adresem nie istnieje, a zostanie wywołana funkcja/metoda Open(), plik ten zostanie utworzony. Jednak nie zalecane jest tworzenie w ten sposób nowych plików, z tego względu, że mogą one zawierać później błędy.

Po utworzeniu i otwarciu pliku, należy w bazie danych utworzyć nową tabelę. Przedstawię najpierw, jak wygląda składnia wysłania zapytania bez zwrotu danych.

Kod: Zaznacz cały

//zmienna przechowująca obiekt do wysyłania zapytań
SQLiteCommand db_command;           

//utworzenie obiektu który odpowiada za wysyłanie zapytania
db_command = new SQLiteCommand(db_querry, db_connect);

//wykonanie/wysłanie zapytania
db_command.ExecuteNonQuery();


W pierwszej kolejności tworzona jest zmienna przechowująca obiekt odpowiedzialny za wysyłanie zapytania, a w kolejnej tworzony jest ten obiekt. Przekazywane jest do niego zapytanie (db_querry w moim przypadku jest zmienną typu string, która zawiera składnię zapytania), oraz zmienna przechowująca obiekt podłączonej bazy danych, który został utworzony przed jego otwarcie. Po utworzeniu obiektu, wykonywane jest jego zapytanie poprzez wywołanie funkcji odpowiedzialnej za przesłanie zapytania które nie zwraca odpowiedzi.

Przykład tworzenia nowego pliku wraz z utworzeniem nowej tabli przedstawia się następująco:

Kod: Zaznacz cały

public string path = null;                  //zmienna przechowująca lokalizację bazy danych
public SQLiteConnection db_connect;         //zmienna przechowująca obiekt bazy danych
public string db_querry = null;             //zmienna przechowująca zapytanie do bazy danych
public SQLiteCommand db_command;            //zmienna przechowująca obiekt do wysyłania zapytań

//tworzenie nowego pliku i tutaj po tym należy utworzyć tabelę w nowej bazie
SQLiteConnection.CreateFile(path);

//utworzenie obiektu potrzebnego do połączenia się z bazą, składnia wymagana przez bibliotekę.
db_connect = new SQLiteConnection("Data Source =" + path + ";Version=3;");

//połączenie się z bazą danych - funkcja tworząca nowy plik nie powoduje otwarcia go
db_connect.Open();

//utworzenie nowego zapytania dotyczącego utworzenia nowej tabeli w bazie danych
db_querry = "CREATE TABLE 'Osoby' ( 'Imie' TEXT, 'Nazwisko' TEXT)";

//utworzenie obiektu który odpowiada za wysyłanie zapytania
db_command = new SQLiteCommand(db_querry, db_connect);

//wykonanie/wysłanie zapytania
db_command.ExecuteNonQuery();

//zamknięcie połączenia z bazą danych
db_connect.Close();


W tym przypadku tworzona jest nowa tabela która nosi nazwę "Osoby". Będzie ona zawierała kolumny "Imie" , oraz "Nazwisko" , których zawartość będzie typu TEXT.

Natomiast dodanie nowych danych do tabeli wygląda następująco:

Kod: Zaznacz cały

//utworzenie nowego zapytania dodającego nowe dane do bazy
db_querry = "INSERT INTO 'Osoby' ('Imie', 'Nazwisko') VALUES ('"+ textBox2.Text +"','" + textBox3.Text + "');";

//utworzenie obiektu który odpowiada za wysyłanie zapytania
db_command = new SQLiteCommand(db_querry, db_connect);

//wykonanie/wysłanie zapytania
db_command.ExecuteNonQuery();


Do tabeli "Osoby" do kolumny "Imie" , oraz "Nazwisko" dodane są wartości wpisane do textbox2, oraz textbox3.

Kolejna czynność jaka jest wykonywana przy korzystaniu z bazy danych, to odczyt danych z tabeli bazy danych. Aby tego dokonać, należy najpierw utworzyć nową zmienną, z której będziemy odczytywać dane z kolejnych kolumn.

Kod: Zaznacz cały

//zmienna przechowująca odebrane informacje zwrócone dla zapytania doczytująceg
SQLiteDataReader db_read;


Następnie do tej zmiennej przypisuje się rezultat jaki zwraca funkcja wysyłająca zapytanie związane z odczytem danych.

Kod: Zaznacz cały

//wykonanie zapytania odczytującego dane z bazy danych
db_read = db_command.ExecuteReader();


Tak odebrane dane z lokalnej bazy danych, są teraz gotowe aby je odczytać. Dokonuje się tego poprzez wywoływanie funkcji Read() - przed pierwszym odczytaniem danych należy również ją wywołać. Odczyt danych wykonuje się wiersz po wierszu, tzn. wywołanie funkcji Read powoduje przejście do następnego wiersza. Odczytywanie danych dokonuje się poprzez odczyt każdej komórki z osobna. Dokonuje się tego po kolei dla każdego wiersza wskazując odpowiednią kolumną:

Kod: Zaznacz cały

db_read.Read();                                 //przed pierwszym użyciem też należy użyć funkcji odczytującej dane z bazy
label2.Text = db_read["Imie"].ToString();       //odczytywanie dokonuje się poprzez wskazanie nazyw kolumny
label3.Text = db_read[1].ToString();            //bądź poprzez podanie numeru kolumny - liczenie od 0


Odczyt danych z odpowiedniej kolumny dokonuje się jak odczyt z tabeli 1-wymiarowej. Można wykorzystać do tego indeks kolumny (liczy się od 0) bądź nazwę kolumny w bazie danych.

Poniżej zamieszczam cały przykład umożliwiający odczytanie danych z bazy danych.

Kod: Zaznacz cały

//zmienna przechowująca odebrane informacje zwrócone dla zapytania doczytująceg
public SQLiteDataReader db_read;           

//utworzenie nowego zapytania powodującego odczytanie/wyszukanie wszystkich danych z bazy
db_querry = "SELECT * FROM 'Osoby'";

//utworzenie obiektu który odpowiada za wysyłanie zapytania
db_command = new SQLiteCommand(db_querry, db_connect);

//wykonanie zapytania odczytującego dane z bazy danych
db_read = db_command.ExecuteReader();

//odczytywanie danych
db_read.Read();                                 //przed pierwszym użyciem też należy użyć funkcji odczytującej dane z bazy
label2.Text = db_read["Imie"].ToString();       //odczytywanie dokonuje się poprzez wskazanie nazyw kolumny
label3.Text = db_read[1].ToString();            //bądź poprzez podanie numeru kolumny - liczenie od 0


Należy wspomnieć również o tym, że w przypadku, gdy zostanie osiągnięty ostatni indeks, dane przestaną być odczytywane. Warto w tej procedurze (jak i w pozostałych procedurach) wykorzystać składnię do przechwytywanie błędu try - catch, aby program nie zakończył swojego żywota. Aby po osiągnięciu ostatniego indeksu móc od początku odczytywać dane, należy wykonać procedurę odczytu od początku, tzn. odłączyć się od bazy danych, połączyć się z nią na nowo i wykonać zapytanie.

I to tyle z części programistycznej. Wydaje mi się, że nie jest to trudne zagadnie, więc początkujący raczej powinien dać radę ze zrozumieniem tego.

Po poprawnym skompilowaniu programu w folderze DEBUG naszego projektu znajduje się plik wykonywalny naszego projektu wraz z pozostałymi plikami. Poniżej na zdjęciach przedstawiam, jakie pliki muszą znaleźć się na innym komputerze aby program działał prawidłowo (wersja minimalistyczna i maksymalistyczna ;) ).

pliki_minimum.jpg

pliki_max.jpg

Mam nadzieję, że w prosty i w przyjazny sposób udało mi się przedstawić obsługę biblioteki SQLite

:arrow: W przypadku jakichś błędów, czy pytań pisać. Każda forma krytyki będzie motywująca;)

Jeszcze w załączniku przesyłam cały program wraz z komentarzami, aby każdy mógł sprawdzić jak to działa, oraz bardziej złożony program typu książka adresowa, która przedstawia w bardziej rozwinięty sposób obsługę bazy danych.
Program książka adresowa jest tylko programem demonstracyjnym, więc mogą wystąpić błędy w pewnych czynnościach których nie przewidziałem.

Z programów tych usunąłem folder package, aby mniej zajmował. Po ściągnięciu i rozpakowaniu projektu należy go najpierw skompilować. Brakuje pliki powinny zostać ściągnięte automatycznie z internetu (bądź z dysku jeżeli się na nim znajdują).

Cs_03_baza_danych_sqlite.zip
Cs_N04_Baza_danych_SQLite-Książka_adr.zip
Nie masz wymaganych uprawnień, aby zobaczyć pliki załączone do tego posta.
Można wszystko osiągnąć, wystarczy chcieć.

Awatar użytkownika
Antystatyczny
Geek
Geek
Posty: 1168
Rejestracja: czwartek 03 wrz 2015, 22:02

Re: [Visual 2015 C# Windows Forms] Obsługa lokalnej bazy danych z wykorzystaniem SQLite - językiem początkującego.

Postautor: Antystatyczny » czwartek 19 maja 2016, 01:47

Witam serdecznie.

Napisałeś, że brakujące pliki zostaną automatycznie ściągnięte z internetu, o ile nie znajdują się jeszcze na czyimś dysku. Rozumiem, że w typowym przypadku pliki te znajdują się w folderze "package", tak? Chodzi mi o teoretyczną możliwość zainstalowania programu na komputerze, który np. nie ma połączenia z internetem. Instaluję, uruchamiam i ma działać. Da się tak?
"The true sign of intelligence is not knowledge but imagination" Albert Einstein.

Awatar użytkownika
danielos
Newb
Newb
Posty: 69
Rejestracja: sobota 02 sty 2016, 15:06
Lokalizacja: Pawłowice, Silesia.
Kontaktowanie:

Re: [Visual 2015 C# Windows Forms] Obsługa lokalnej bazy danych z wykorzystaniem SQLite - językiem początkującego.

Postautor: danielos » czwartek 19 maja 2016, 07:15

Witam.

Chyba źle się wyraziłem. Pliki, których brakuje (brak folderu package) są wymagane tylko i wyłącznie przy otwarciu i kompilacji projektu w samym programie/środowisku Visual Studio - sam program (uruchomiony plik *.exe) bez tego folderu będzie działał.
Chciałem umieścić przykładowe projekty, aby każdy mógł sobie sam skompilować i sprawdzić jak wszystko działa z bazą danych - nie chciałem całości projektu przesyłać, gdyż pliki te ważyłyby około 50MB.

Program (w tym przypadku) który znajduje się w folderze DEBUG (ostatecznie będzie to RELEASE) posiada wszystkie wymagające pliki.
Uruchamiając sam program, np. Cs_03_baza_danych_sqlite.exe znajdujący się w folderze DEBUG, powinien działać bez problemu, gdyż wszystkie wymagające pliki znajdują się w tym folderze (na dwóch ostatnich zdjęciach przedstawione jest, jakie są wymagane pliki aby program działał prawidłowo).

Podsumowując moją plątaninę słów:
Aby przenieść program na inny komputer wystarczy skopiować folder w którym znajduje się skompilowany program (w moim przypadku na chwilę obecną jest to DEBUG, ostatecznie będzie RELEASE) i będzie działać.

Edit - 21.05.2016r.:
Zapomniałem dodać, że wymagany jest .NET Framework.
Można wszystko osiągnąć, wystarczy chcieć.


Wróć do „Pisanie programów w C#”

Kto jest online

Użytkownicy przeglądający to forum: Obecnie na forum nie ma żadnego zarejestrowanego użytkownika i 3 gości