Bazy danych w aplikacji mobilnej (.NET MAUI + SQLite)


Wstęp — po co baza danych?

Wyobraź sobie, że tworzysz aplikację do notatek.

  • W pliku TXT możesz zapisać jedną długą notatkę.
  • W JSON możesz zapisać listę obiektów (np. {„Tytuł”: „Zakupy”, „Treść”: „Mleko, chleb”}).
  • Ale co, jeśli chcesz mieć 1000 notatek, sortować je, wyszukiwać, filtrować?

Do tego służy baza danych — specjalny plik, w którym dane są ułożone w tabele (tak jak w Excelu).
Najpopularniejsza w aplikacjach mobilnych jest SQLite.

Dlaczego SQLite?

  • jest lekka – cała baza to jeden plik .db,
  • działa na Androidzie, Windowsie i iOS,
  • nie wymaga serwera (działa offline),
  • obsługuje normalne zapytania SQL (SELECT, INSERT, UPDATE, DELETE).

Na egzaminie INF.04, jeśli pojawia się baza w aplikacji mobilnej, to zawsze SQLite.


Co przygotować w Visual Studio 2022

  1. Otwórz swój projekt MAUI.
  2. Kliknij prawym na projekt → Manage NuGet Packages…
    • Wyszukaj i zainstaluj:
      • sqlite-net-pcl (najczęściej używana biblioteka).
  3. Dodaj nowy folder w projekcie: Models (na klasy tabel).
  4. Dodaj nowy folder: Data (na obsługę bazy).
  5. Baza danych będzie zapisana w folderze FileSystem.AppDataDirectory.

Tworzymy model danych (tabela w bazie)

  1. W folderze Models dodaj nowy plik: Notatka.cs (Add → Class).
  2. Wklej kod:
using SQLite;

namespace BazyDemo.Models;

// Model odpowiada tabeli "Notatka" w SQLite
public class Notatka
{
    [PrimaryKey, AutoIncrement]    // klucz główny, autoinkrementacja
    public int Id { get; set; }

    [MaxLength(100)]               // maksymalnie 100 znaków
    public string Tytul { get; set; } = "";

    public string Tresc { get; set; } = "";
}

Tworzymy obsługę bazy (klasa serwisu)

  1. W folderze Data dodaj nowy plik: NotatkaDatabase.cs (Add → Class).
  2. Wklej kod:
using SQLite;
using BazyDemo.Models;

namespace BazyDemo.Data;

public class NotatkaDatabase
{
    private readonly SQLiteAsyncConnection _database;

    // Konstruktor - tworzy plik bazy w AppDataDirectory
    public NotatkaDatabase(string dbPath)
    {
        _database = new SQLiteAsyncConnection(dbPath);
        _database.CreateTableAsync<Notatka>().Wait();  // tworzy tabelę jeśli nie istnieje
    }

    // Operacje CRUD:
    public Task<List<Notatka>> GetNotatkiAsync()
        => _database.Table<Notatka>().ToListAsync();

    public Task<int> ZapiszNotatkeAsync(Notatka notatka)
        => _database.InsertAsync(notatka);

    public Task<int> UsunNotatkeAsync(Notatka notatka)
        => _database.DeleteAsync(notatka);
}

Inicjalizacja bazy w App.xaml.cs

Otwórz plik App.xaml.cs i dodaj:

using BazyDemo.Data;

namespace BazyDemo;

public partial class App : Application
{
    // Statyczne pole bazy - dostępne z każdej strony
    public static NotatkaDatabase Database { get; private set; }

    public App()
    {
        InitializeComponent();

        // pełna ścieżka do pliku bazy
        string dbPath = Path.Combine(FileSystem.AppDataDirectory, "notatki.db3");

        Database = new NotatkaDatabase(dbPath);

        MainPage = new AppShell();
    }
}

Strona z listą notatek

  1. Dodaj nową stronę: NotatkiPage.xaml (Add → New Item → .NET MAUI ContentPage (XAML)).
  2. Wklej kod XAML:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="BazyDemo.NotatkiPage"
             Title="Notatki">

    <VerticalStackLayout Padding="16" Spacing="12">

        <Entry x:Name="TytulEntry"
               Placeholder="Tytuł notatki" />

        <Editor x:Name="TrescEntry"
                Placeholder="Treść notatki"
                AutoSize="TextChanges"
                HeightRequest="120"
                Margin="0,4,0,0" />

        <Button Text="Dodaj notatkę"
                Clicked="Dodaj_Click"
                Margin="0,8,0,0" />

        <CollectionView x:Name="ListaNotatek"
                        HeightRequest="300"
                        SelectionMode="Single"
                        Margin="0,12,0,0">
            <CollectionView.ItemTemplate>
                <DataTemplate>
                    <Frame BorderColor="Gray"
                           Padding="8"
                           Margin="0,6"
                           HasShadow="False">
                        <VerticalStackLayout Spacing="4">
                            <Label Text="{Binding Tytul}"
                                   FontAttributes="Bold"
                                   FontSize="16" />
                            <Label Text="{Binding Tresc}"
                                   FontSize="14"
                                   LineBreakMode="WordWrap" />
                        </VerticalStackLayout>
                    </Frame>
                </DataTemplate>
            </CollectionView.ItemTemplate>
        </CollectionView>

        <Button Text="Usuń zaznaczoną"
                Clicked="Usun_Click"
                Margin="0,8,0,0" />

    </VerticalStackLayout>
</ContentPage>

Logika w NotatkiPage.xaml.cs

using BazyDemo.Models;

namespace BazyDemo;

public partial class NotatkiPage : ContentPage
{
    public NotatkiPage()
    {
        InitializeComponent();
        WczytajNotatki();   // ładowanie przy starcie
    }

    private async void WczytajNotatki()
    {
        ListaNotatek.ItemsSource = await App.Database.GetNotatkiAsync();
    }

    private async void Dodaj_Click(object sender, EventArgs e)
    {
        if (!string.IsNullOrWhiteSpace(TytulEntry.Text))
        {
            var nowa = new Notatka
            {
                Tytul = TytulEntry.Text,
                Tresc = TrescEntry.Text
            };
            await App.Database.ZapiszNotatkeAsync(nowa);

            TytulEntry.Text = "";
            TrescEntry.Text = "";
            WczytajNotatki();
        }
        else
        {
            await DisplayAlert("Błąd", "Podaj tytuł notatki", "OK");
        }
    }

    private async void Usun_Click(object sender, EventArgs e)
    {
        if (ListaNotatek.SelectedItem is Notatka wybrana)
        {
            await App.Database.UsunNotatkeAsync(wybrana);
            WczytajNotatki();
        }
        else
        {
            await DisplayAlert("Info", "Najpierw zaznacz notatkę", "OK");
        }
    }
}

Wyjaśnienie krok po kroku

  • Model (Notatka.cs) → klasa = tabela w SQLite.
  • Database (NotatkaDatabase.cs) → obsługuje zapytania (CRUD).
  • App.xaml.cs → tworzy bazę i przechowuje globalne Database.
  • NotatkiPage.xaml → UI: pola, przyciski, lista.
  • NotatkiPage.xaml.cs → logika:
    • Dodaj_Click → zapis do bazy,
    • WczytajNotatki() → SELECT,
    • Usun_Click → DELETE.

Podsumowanie

  • SQLite to lokalna baza danych – działa w pliku .db3.
  • Każda tabela to klasa modelu.
  • Obsługę bazy umieszczamy w osobnym serwisie (Database).
  • Typowe operacje: Insert, Select, Delete – wystarczą na INF.04.
  • Dzięki CollectionView możemy ładnie wyświetlać dane z bazy.