SQLiteXM 1.2.0
dotnet add package SQLiteXM --version 1.2.0
NuGet\Install-Package SQLiteXM -Version 1.2.0
<PackageReference Include="SQLiteXM" Version="1.2.0" />
<PackageVersion Include="SQLiteXM" Version="1.2.0" />
<PackageReference Include="SQLiteXM" />
paket add SQLiteXM --version 1.2.0
#r "nuget: SQLiteXM, 1.2.0"
#:package SQLiteXM@1.2.0
#addin nuget:?package=SQLiteXM&version=1.2.0
#tool nuget:?package=SQLiteXM&version=1.2.0
SQLiteXM for .NET MAUI
SQLiteXM is a high-performance, entity-first ORM for SQLite designed specifically for .NET MAUI applications.
Why SQLiteXM?
We asked ourselves: “What would a deliberately designed SQLite persistence layer for modern .NET/MAUI applications look like—one that supports SQL and LINQ while still providing convenient entities, schema evolution, transactions, mapping, persistence methods, and UI binding?”
The result is SQLiteXM.
| Capability | SQLiteXM |
|---|---|
| Designed specifically for .NET MAUI + SQLite | ✅ |
| AOT/IL Trimming Safe — works with MAUI's default Release trimming, no linker configuration needed (details) | ✅ |
| Mobile-optimized database initialization — idempotent, concurrency-safe startup from any entry point | ✅ |
| LINQ query support | ✅ |
| Raw SQL Support | ✅ |
| Automatic entity-to-table mapping | ✅ |
| Built-in schema evolution | ✅ |
| SQLite PRAGMAS are first-class initialization options | ✅ |
| Multiple SQLite Database Support | ✅ |
| Full Transaction Support — explicit and ambient transaction patterns | ✅ |
| Handles mobile lifecycle events — app suspend/resume | ✅ |
| Entities are MAUI binding-ready with INotifyPropertyChanged support | ✅ |
| Async-first design — supports non-blocking UI patterns | ✅ |
| Minimal configuration — no migration files, no DbContext setup | ✅ |
| Automated Test Coverage | 250+ tests |
📖 Documentation
See the Documentation Guide to find the right guide for where you are in your project.
🎮 Try SQLiteXM with the Query Gallery Demo
Want to see SQLiteXM in action? Download the pre-built Query Gallery Demo application:
This is a ready-to-run MAUI Windows application that showcases SQLiteXM through working query examples organized into 10 categories.
📥 Download QueryGalleryDemo_Windows.zip
This demo runs completely self-contained. Simply extract the ZIP file on Windows and run QueryGalleryDemo.exe to explore LINQ queries, joins, aggregations, transactions, and more.
Features:
- ✅ 100+ working query examples (LINQ and SQL) across 10 categories
- ✅ Live code execution with performance metrics
- ✅ Realistic music database (~25,000 records)
Want more details? See the Query Gallery Demo
🎯 SQLiteXM Quick Start (3 Minutes)
1. Define Your Entities
Create classes that inherit from SxmEntity:
using SQLiteXM;
[Table(IsColumnAttributeRequired = false)]
public class User : SxmEntity
{
public string? Name { get; set; }
public int Age { get; set; }
public DateTime CreatedAt { get; set; }
[Index]
public string? Email { get; set; }
}
[Table(IsColumnAttributeRequired = false)]
public class Post : SxmEntity
{
public string? Title { get; set; }
public string? Content { get; set; }
[ForeignKey(ForeignTable = nameof(User))]
public long UserId { get; set; }
}
What's happening?
SxmEntitymarks the class as a database-mapped entity[Table]defines schema behavior for the entity[Index]declares a database index on the property[ForeignKey]defines relational constraints between entities
The schema is created when the database is initialized with StartInitialization(...) (step 3).
2. Create SqlStatements.json File
Place this file in Resources/Raw (Build Action: MauiAsset):
{
"databases": [
{
"database": "MyAppDatabase",
"isDefault": true
}
]
}
What's happening?
- Defines the SQLite database configuration for the application
databasespecifies the SQLite database nameisDefaultassigns the default database for entities without an explicit database assignment- The configuration is loaded during initialization to establish database connections and schema management
3. Initialize SQLiteXM
Once your entities and database configuration are defined, you're ready to initialize the database.
// Create an array containing all the entities used by your application
Type[] applicationEntities = new Type[]
{
typeof(User),
typeof(Post)
};
// Open the SqlStatements.json configuration file from the application package
Stream sqlStatementsStream = await FileSystem.OpenAppPackageFileAsync("SqlStatements.json");
// Start database initialization in the background
// SQLiteXM takes ownership of 'sqlStatementsStream' and ensures proper disposal.
SxmDatabase.StartInitialization(sqlStatementsStream, databaseOptions: null, applicationEntities);
Call SxmDatabase.StartInitialization(...) once during application startup. A good place is
in MauiProgram.cs right after calling MauiApp.CreateBuilder(). StartInitialization returns immediately
without blocking - initialization runs in the background.
4. Verifying Database Initialization Has Completed
Before the first use of the database, anywhere in your app, call:
await SxmDatabase.EnsureReadyAsync();
EnsureReadyAsync only needs to be called once. It waits for the database initialization task started by
StartInitialization to complete, guaranteeing that the database is fully initialized and ready for use.
5. Start Reading and Writing Data
Once initialization is complete, SQLiteXM is ready for normal application use. You can create and save entities, query and modify data using LINQ or SQL, and begin using transactions.
// 'User' inherits from SxmEntity and is automatically mapped to a database table
var user = new User
{
Name = "Alice",
Age = 0,
Email = "alice@example.com",
CreatedAt = DateTime.UtcNow
};
// Insert 'user' into the database
// 'Age' is initially set to 0; the record is updated below.
await user.SaveAsync();
await using (var ctx = new SxmTransaction())
{
// LINQ — query the user to modify.
var existingUser = ctx.GetTable<User>().FirstOrDefault(u => u.Name == "Alice");
// Embedded SQL — execute SQL within the same transaction.
await ctx.RunStatementAsync("UPDATE User SET LastLogin = CURRENT_TIMESTAMP WHERE Name == 'Alice'");
// Entity DML — persist the change.
// Uses the active transaction.
existingUser.Age = 25;
await existingUser.SaveAsync();
} // <-- Automatically commits transaction on dispose if no errors occurred
What's happening?
SaveAsync()inserts a new entity or updates an existing entity based on its primary keySxmTransactionstarts a new transaction scope for database operations- All database operations within the transaction participate in the same commit scope
- LINQ executes against the database and returns an entity instance
RunStatementAsync()executes embedded SQL within the active transaction- Entity instances can be modified and persisted using the same
SaveAsync
🧪 Testing
SQLiteXM includes a comprehensive test suite with 250+ tests covering real-world scenarios.
Performance Benchmarks (from test suite)
| Operation | Time | Details |
|---|---|---|
| 10,000 row insert (transacted) | 0.45s | Using explicit transaction |
| 50,000 row query | 14ms | With index |
| Complex LINQ (20K rows) | 12ms | Joins + filters |
| 100 concurrent writes | 1.2s | Thread-safe operations |
Benchmark results are environment-dependent and are provided as indicative results from the project's test suite rather than universal performance guarantees.
Test Coverage
| Category | Tests | Status |
|---|---|---|
| Entity CRUD | 11 tests | ✅ 100% |
| Entity Initialization | 13 tests | ✅ 100% |
| Entity Migration | 18 tests | ✅ 100% |
| Entity Mapping | 4 tests | ✅ 100% |
| Initialization Stress Tests (Idempotency and Concurrency) | 11 tests | ✅ 100% |
| LINQ Queries | 7 tests | ✅ 100% |
| Advanced LINQ | 12 tests | ✅ 100% |
| LINQ Transactions | 6 tests | ✅ 100% |
| Bulk LINQ Operations | 11 tests | ✅ 100% |
| Transactions | 7 tests | ✅ 100% |
| Multi-Database | 11 tests | ✅ 100% |
| Multi-Database LINQ | 18 tests | ✅ 100% |
| Multi-Database Performance | 10 tests | ✅ 100% |
| LINQ documentation tests | 43 tests | ✅ 100% |
| Drop Table | 22 tests | ✅ 100% |
| Column Rename | 10 tests | ✅ 100% |
| Shared Connections | 7 tests | ✅ 100% |
| Connection Workers | 7 tests | ✅ 100% |
| Submit Changes | 4 tests | ✅ 100% |
| Fail-Fast Validation | 5 tests | ✅ 100% |
| Mixed Operation Transactions | 13 tests | ✅ 100% |
| Total | 250+ tests | ✅ 100% |
📚 Sample Applications
SQLiteXM includes three sample applications to help you learn:
1. QueryGalleryDemo (Comprehensive) ⭐
An interactive query explorer with 100+ examples. Features: Syntax highlighting, runnable examples, execution timing, result visualization.
<details> <summary>📖 Query Gallery Details</summary>
- ✅ Basic Queries 10 - simple select, where, order by
- 🔗 Relationships 8 - join queries, navigation
- 📊 Aggregations 10 - count, sum, group by, avg
- 📦 Advanced LINQ 11 - complex queries, paging
- 🎯 Raw SQL 15 - direct SQL execution
- 📈 Performance 9 - large data sets, benchmarks
- 🔄 Many-to-Many 8 - junction tables, relationships
- 💾 Transactions 6 - atomic operations, rollback
- ⚡ Parameterized Queries 6 - prevent SQL injection
- 💾 Data modification 8 - insert, update, delete examples </details>
2. RegistrationDemo (Simple)
Basic user registration showing entity definition, save/query, and data binding.
3. DirectBindingDemo (Simple)
CollectionView binding with CRUD operations and UI updates.
📦 Installation
dotnet add package SQLiteXM
Or install via the NuGet Package Manager
🛠️ Requirements
- .NET MAUI Project
Platforms: iOS, Android, macOS, Windows (any .NET MAUI supported platform)
<a id="aot-trimming"></a>
✂️ AOT and IL Trimming Safe — Out of the Box
.NET MAUI trims your app in Release builds, and AOT-compiles it on iOS and Mac Catalyst. Reflection-based ORMs
often break here: entity properties are trimmed away and mappings fail at runtime — but only on a device, never
in Debug. The usual fix is to sprinkle [Preserve] or [DynamicDependency] attributes on your entities, add a
TrimmerRootDescriptor.xml, or turn trimming off. That work lands on you.
SQLiteXM removes that burden:
- Zero trim/AOT analyzer warnings. SQLiteXM is built with
IsTrimmableandIsAotCompatibleand compiles cleanly under the .NET trim and AOT analyzers. - Your entities are preserved automatically. Every SQLiteXM API that accepts an entity type is annotated with
DynamicallyAccessedMembers, so the trimmer keeps your entity classes intact without any attributes, linker files, or project changes on your side. - Works with MAUI's defaults. Create a MAUI project, add SQLiteXM, define your entities, build in Release. Nothing to configure. Verified against MAUI's default Release trimming on .NET 8 and .NET 9.
As with any MAUI project, run your Release build on a device or emulator before shipping — Debug builds do not trim, so that is the only place trimming behavior can be observed.
📄 License
MIT License - see LICENSE for details.
🙏 Acknowledgments
- SQLite provider via Microsoft.Data.Sqlite (MIT License)
- LINQ support via LinqToDB (MIT License)
Inspired by Entity Framework Core, Dapper, and SQLite-net
Made with ❤️ for the .NET MAUI community
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net8.0
- linq2db (>= 6.3.0)
- Microsoft.Data.Sqlite (>= 10.0.10)
-
net9.0
- linq2db (>= 6.3.0)
- Microsoft.Data.Sqlite (>= 10.0.10)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.