| MAUI-with-SQLite | MAUI-SQLite-CRUD | |
SQLite Basics in .NET MAUI - Step-by-Step Checklist Tutorial |
SQLite basics in .NET MAUI into a step-by-step checklist tutorial you can follow while coding. This way, you’ll have a clear roadmap from setup to CRUD operations.
Add sqlite-net-pcl to your MAUI project.
This gives you async SQLite support with simple ORM features.
dotnet add package sqlite-net-pcl
Define a class with attributes for SQLite mapping.
using SQLite;
public class TodoItem
{
[PrimaryKey, AutoIncrement]
public int Id { get; set; }
[MaxLength(250)]
public string Name { get; set; }
public bool IsCompleted { get; set; }
}
Encapsulate database logic in a helper class.
public class DatabaseService
{
readonly SQLiteAsyncConnection _database;
public DatabaseService(string dbPath)
{
_database = new SQLiteAsyncConnection(dbPath);
_database.CreateTableAsync<TodoItem>().Wait();
}
public Task<List<TodoItem>> GetItemsAsync() =>
_database.Table<TodoItem>().ToListAsync();
public Task<int> SaveItemAsync(TodoItem item) =>
_database.InsertOrReplaceAsync(item);
public Task<int> DeleteItemAsync(TodoItem item) =>
_database.DeleteAsync(item);
}
Store the .db3 file in the app’s data directory.
string dbPath = Path.Combine(FileSystem.AppDataDirectory, "mydb.db3"); var db = new DatabaseService(dbPath);
Bind a CollectionView or ListView to GetItemsAsync().
Add buttons or swipe gestures for Add / Update / Delete.
Example (simplified):
<CollectionView ItemsSource="{Binding Items}">
<CollectionView.ItemTemplate>
<DataTemplate>
<StackLayout Orientation="Horizontal">
<Label Text="{Binding Name}" />
<CheckBox IsChecked="{Binding IsCompleted}" />
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
Register DatabaseService in MauiProgram.cs:
builder.Services.AddSingleton<DatabaseService>(
s => new DatabaseService(
Path.Combine(FileSystem.AppDataDirectory, "mydb.db3")));
Inject it into your ViewModels for clean architecture.
A ready-made sample project structure you can drop into your MAUI solution. This will give you a clean architecture with folders for Models, Services, ViewModels, and Views, all wired up to SQLite.
MyMauiApp/ │ ├── Models/ │ └── TodoItem.cs │ ├── Services/ │ └── DatabaseService.cs │ ├── ViewModels/ │ └── TodoViewModel.cs │ ├── Views/ │ └── TodoPage.xaml │ └── TodoPage.xaml.cs │ ├── MauiProgram.cs └── App.xaml / App.xaml.cs
using SQLite;
namespace MyMauiApp.Models;
public class TodoItem
{
[PrimaryKey, AutoIncrement]
public int Id { get; set; }
[MaxLength(250)]
public string Name { get; set; }
public bool IsCompleted { get; set; }
}
using SQLite;
using MyMauiApp.Models;
namespace MyMauiApp.Services;
public class DatabaseService
{
readonly SQLiteAsyncConnection _database;
public DatabaseService(string dbPath)
{
_database = new SQLiteAsyncConnection(dbPath);
_database.CreateTableAsync<TodoItem>().Wait();
}
public Task<List<TodoItem>> GetItemsAsync() =>
_database.Table<TodoItem>().ToListAsync();
public Task<int> SaveItemAsync(TodoItem item) =>
_database.InsertOrReplaceAsync(item);
public Task<int> DeleteItemAsync(TodoItem item) =>
_database.DeleteAsync(item);
}
using System.Collections.ObjectModel;
using MyMauiApp.Models;
using MyMauiApp.Services;
namespace MyMauiApp.ViewModels;
public class TodoViewModel : BindableObject
{
private readonly DatabaseService _db;
public ObservableCollection<TodoItem> Items { get; } = new();
public TodoViewModel(DatabaseService db)
{
_db = db;
LoadItems();
}
private async void LoadItems()
{
var items = await _db.GetItemsAsync();
Items.Clear();
foreach (var item in items)
Items.Add(item);
}
public async Task AddItem(string name)
{
var newItem = new TodoItem { Name = name, IsCompleted = false };
await _db.SaveItemAsync(newItem);
LoadItems();
}
public async Task ToggleItem(TodoItem item)
{
item.IsCompleted = !item.IsCompleted;
await _db.SaveItemAsync(item);
LoadItems();
}
public async Task DeleteItem(TodoItem item)
{
await _db.DeleteItemAsync(item);
LoadItems();
}
}
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
x:Class="MyMauiApp.Views.TodoPage"
Title="Todo List">
<VerticalStackLayout Padding="20">
<Entry x:Name="NewItemEntry" Placeholder="Enter new task..." />
<Button Text="Add" Clicked="OnAddClicked" />
<CollectionView ItemsSource="{Binding Items}">
<CollectionView.ItemTemplate>
<DataTemplate>
<StackLayout Orientation="Horizontal" Padding="5">
<Label Text="{Binding Name}" VerticalOptions="Center" />
<CheckBox IsChecked="{Binding IsCompleted}" />
<Button Text="Delete" CommandParameter="{Binding .}" />
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</VerticalStackLayout>
</ContentPage>
using MyMauiApp.ViewModels;
using MyMauiApp.Models;
namespace MyMauiApp.Views;
public partial class TodoPage : ContentPage
{
private readonly TodoViewModel _vm;
public TodoPage(TodoViewModel vm)
{
InitializeComponent();
BindingContext = _vm = vm;
}
private async void OnAddClicked(object sender, EventArgs e)
{
if (!string.IsNullOrWhiteSpace(NewItemEntry.Text))
{
await _vm.AddItem(NewItemEntry.Text);
NewItemEntry.Text = string.Empty;
}
}
}
using MyMauiApp.Services;
using MyMauiApp.ViewModels;
using MyMauiApp.Views;
namespace MyMauiApp;
public static class MauiProgram
{
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp<App>();
// Register DatabaseService
builder.Services.AddSingleton<DatabaseService>(
s => new DatabaseService(
Path.Combine(FileSystem.AppDataDirectory, "mydb.db3")));
// Register ViewModel
builder.Services.AddTransient<TodoViewModel>();
// Register Page
builder.Services.AddTransient<TodoPage>();
return builder.Build();
}
}
| MAUI-with-SQLite | MAUI-SQLite-CRUD | |