Search This Blog

Tuesday, 30 June 2026

Local SQLite Database in .NET MAUI Complete CRUD Tutorial

Almost every mobile app needs to save data on the device – notes, settings, a cart, cached records. In .NET MAUI the easiest and most popular way to do this is with a local SQLite database. In this tutorial you will build a small Notes app and implement a complete CRUD (Create, Read, Update, Delete) workflow using the sqlite-net-pcl library.

What you will learn

  • How to add SQLite to a .NET MAUI project
  • How to create a model and a reusable database service
  • How to Insert, Read, Update and Delete records asynchronously
  • Where the database file lives on the device

Step 1 – Install the NuGet packages

Right‑click your project → Manage NuGet Packages and install:

  • sqlite-net-pcl – the ORM that lets you work with C# objects instead of raw SQL
  • SQLitePCLRaw.bundle_green – the native SQLite engine (usually pulled in automatically)
dotnet add package sqlite-net-pcl

Step 2 – Create the model

A model is just a plain C# class. The SQLite attributes tell the library how to build the table.

using SQLite;

namespace MauiSqliteDemo.Models;

public class Note
{
    [PrimaryKey, AutoIncrement]
    public int Id { get; set; }

    public string Title { get; set; } = string.Empty;

    public string Description { get; set; } = string.Empty;

    public DateTime CreatedAt { get; set; } = DateTime.Now;
}

Step 3 – Create the database service

This class opens the connection, creates the table on first use, and exposes async methods for every CRUD operation. Notice the lazy Init() pattern – the connection is only created once.

using SQLite;
using MauiSqliteDemo.Models;

namespace MauiSqliteDemo.Services;

public class NoteDatabase
{
    private SQLiteAsyncConnection _database;

    private async Task Init()
    {
        if (_database is not null)
            return;

        var dbPath = Path.Combine(FileSystem.AppDataDirectory, "notes.db3");
        _database = new SQLiteAsyncConnection(dbPath);
        await _database.CreateTableAsync<Note>();
    }

    // READ (all)
    public async Task<List<Note>> GetNotesAsync()
    {
        await Init();
        return await _database.Table<Note>().ToListAsync();
    }

    // READ (single)
    public async Task<Note> GetNoteAsync(int id)
    {
        await Init();
        return await _database.Table<Note>()
                              .Where(n => n.Id == id)
                              .FirstOrDefaultAsync();
    }

    // CREATE + UPDATE
    public async Task<int> SaveNoteAsync(Note note)
    {
        await Init();
        if (note.Id != 0)
            return await _database.UpdateAsync(note);   // existing record
        else
            return await _database.InsertAsync(note);   // new record
    }

    // DELETE
    public async Task<int> DeleteNoteAsync(Note note)
    {
        await Init();
        return await _database.DeleteAsync(note);
    }
}

Step 4 – Register the service (Dependency Injection)

Open MauiProgram.cs and register the database as a singleton so the whole app shares one instance.

builder.Services.AddSingleton<NoteDatabase>();

Step 5 – Use it in a page

Inject NoteDatabase through the page constructor and call the methods. Here is a quick example of every operation:

public partial class MainPage : ContentPage
{
    private readonly NoteDatabase _db;

    public MainPage(NoteDatabase db)
    {
        InitializeComponent();
        _db = db;
    }

    private async void OnSaveClicked(object sender, EventArgs e)
    {
        // CREATE
        var note = new Note { Title = "First note", Description = "Hello SQLite" };
        await _db.SaveNoteAsync(note);

        // READ
        List<Note> notes = await _db.GetNotesAsync();

        // UPDATE
        note.Title = "Updated title";
        await _db.SaveNoteAsync(note);

        // DELETE
        await _db.DeleteNoteAsync(note);
    }
}
Tip: FileSystem.AppDataDirectory points to a private folder for your app, so the database is safe and is not visible to the user or other apps.

Conclusion

You now have a fully working local database in .NET MAUI with clean, async CRUD methods. Because the service is registered with dependency injection, you can inject it into any page or view model.

Next, make your UI clean and testable by moving this logic into a view model – read MVVM in .NET MAUI with CommunityToolkit.Mvvm . Happy coding!

No comments:

Post a Comment

Popular Posts