SQLite.Framework.SourceGenerator 5.2.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package SQLite.Framework.SourceGenerator --version 5.2.0
                    
NuGet\Install-Package SQLite.Framework.SourceGenerator -Version 5.2.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="SQLite.Framework.SourceGenerator" Version="5.2.0">
  <PrivateAssets>all</PrivateAssets>
  <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="SQLite.Framework.SourceGenerator" Version="5.2.0" />
                    
Directory.Packages.props
<PackageReference Include="SQLite.Framework.SourceGenerator">
  <PrivateAssets>all</PrivateAssets>
  <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add SQLite.Framework.SourceGenerator --version 5.2.0
                    
#r "nuget: SQLite.Framework.SourceGenerator, 5.2.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package SQLite.Framework.SourceGenerator@5.2.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=SQLite.Framework.SourceGenerator&version=5.2.0
                    
Install as a Cake Addin
#tool nuget:?package=SQLite.Framework.SourceGenerator&version=5.2.0
                    
Install as a Cake Tool

SQLite.Framework

LINQ-to-SQL for SQLite, with the LINQ surface of EF Core but without the runtime weight - and without the trimming and AOT pain that EF Core still has on Native AOT today. Built for .NET MAUI, Avalonia, and any other AOT-published .NET 8/9/10 app where you want to use full-featured IQueryable instead of hand-written SQL.

NuGet codecov

SQLiteOptions options = new SQLiteOptionsBuilder("library.db").Build();
using var db = new SQLiteDatabase(options);

var authors = await (
    from b in db.Table<Book>()
    join a in db.Table<Author>() on b.AuthorId equals a.Id
    where b.Price > 10
    group b by a.Name into g
    orderby g.Sum(x => x.Price) descending
    select new
    {
        Author = g.Key,
        Books = g.Count(),
        Revenue = g.Sum(x => x.Price)
    }
).Skip(10).Take(20).ToListAsync();

That whole expression is one SQL query. The framework keeps the generated SQL close to the shape of the LINQ chain you wrote and does not wrap it in extra subqueries or rewrite it behind your back to make a method work. When a LINQ method does not map cleanly to SQL, you get a clear NotSupportedException instead of a silently rewritten query. No client-side fallback that pulls rows into memory, and no reflection at runtime when you opt into the source generator.

Why this and not...

You're using What you'll like here What you'll lose
EF Core Same IQueryable shape, smaller dependency, AOT works with minimal setup, no migrations or change tracker overhead. EF's full mapping model (owned types, value converters via fluent API, complex inheritance).
sqlite-net-pcl Real LINQ - joins, group-by, subqueries, projections, FTS5, JSON, window functions all translate to SQL. AOT-friendly with the source generator. Nothing meaningful, the API is similar where it overlaps and the migration is small.
Dapper No more raw SQL strings (although you can still call Query and Execute just the same) and type-safe queries. Multi-database support, Dapper isn't SQLite-specific.

See the Migrating from sqlite-net-pcl or Migrating from EF Core page if that's your starting point.

Performance

Head-to-head against EF Core 10 and sqlite-net-pcl 1.9 on the same in-process SQLite file. 100 rows per operation, .NET 10, BenchmarkDotNet. Lower is better.

Read 100 rows into a List<Book>:

ORM Mean Allocated Ratio
SQLite.Framework + SourceGenerator 39.0 μs 21.8 KB 0.56
sqlite-net-pcl 45.0 μs 15.4 KB 0.65
SQLite.Framework (reflection path) 69.7 μs 36.1 KB 1.00
EF Core 10 (AsNoTracking) 77.0 μs 47.6 KB 1.11

Bulk insert 100 rows (single transaction):

ORM Mean Allocated Ratio
SQLite.Framework + SourceGenerator 130.9 μs 7.4 KB 0.91
SQLite.Framework (reflection path) 143.8 μs 16.7 KB 1.00
sqlite-net-pcl (InsertAll) 151.9 μs 20.6 KB 1.06
EF Core 10 (AddRange + SaveChanges) 2,160 μs 918.2 KB 15.02

Bulk update 100 rows by predicate:

ORM Mean Allocated Ratio
SQLite.Framework (ExecuteUpdate) 154.6 μs 17.4 KB 1.00
EF Core 10 (ExecuteUpdate) 187.3 μs 19.3 KB 1.21
sqlite-net-pcl (UpdateAll) 476.9 μs 198.3 KB 3.08

Join + project (1000 Books and 50 Authors, filter Price > 50, sort, project to a DTO):

ORM Mean Allocated Ratio
SQLite.Framework + SourceGenerator 80.6 μs 34.9 KB 0.74
EF Core 10 104.2 μs 61.7 KB 0.96
SQLite.Framework (reflection path) 109.0 μs 45.3 KB 1.00
sqlite-net-pcl 417.0 μs 155.4 KB 3.83

sqlite-net-pcl's TableQuery<T> is IEnumerable<T>, not IQueryable<T>, so the LINQ join binds to Enumerable.Join. The whole Books and Authors tables load into memory before the filter and join run client-side.

Status

The library is exercised at 100% code coverage. It targets .NET 8, 9, and 10.

Documentation

The full docs live at destbg.github.io/SQLite.Framework. Start with the Overview and Getting Started pages.

The same content is also mirrored on the GitHub Wiki, but GitHub Pages is the primary source for the docs.

Installation

dotnet add package SQLite.Framework

The provider packages all expose the same API and assembly name, so you can swap between them without touching code:

Package Use when
SQLite.Framework Default. Uses the SQLite version that ships with the OS.
SQLite.Framework.Bundled Ships its own SQLite binary. Use when the OS-bundled SQLite is too old.
SQLite.Framework.Cipher Uses SQLCipher for encrypted databases.
SQLite.Framework.Base Bring-your-own SQLitePCLRaw provider.

JSON, JSONB, FTS5, and window functions are built into all four.

Quick Start

  1. Define your model.
public class Person
{
    [Key, AutoIncrement]
    public int Id { get; set; }
    public required string Name { get; set; }
    public DateTime? BirthDate { get; set; }
}

Per-class attributes: [Table], [WithoutRowId]. Per-property: [Column], [NotMapped], [Key], [Index], [AutoIncrement], [Required]. Columns are NOT NULL by default, use ? to mark them as nullable.

  1. Open a database.
using SQLite.Framework;

var options = new SQLiteOptionsBuilder("app.db").Build();
using var db = new SQLiteDatabase(options);
db.Schema.CreateTable<Person>();
  1. Write LINQ queries.
db.Table<Person>().Add(new Person { Name = "Alice" });

var adults = (
    from p in db.Table<Person>()
    where p.BirthDate < DateTime.Now.AddYears(-18)
    orderby p.Name
    select new { p.Id, p.Name }
).ToList();
  1. Async works the same way.
await db.Table<Person>().AddAsync(new Person { Name = "Alice" });

var ids = await (
    from p in db.Table<Person>()
    select p.Id
).ToListAsync();
  1. Joins, groupings, projections - all translate to SQL.
var result = await (
    from b in db.Table<Book>()
    join a in db.Table<Author>() on b.AuthorId equals a.Id
    group b by a.Name into g
    select new
    {
        Author = g.Key,
        Count = g.Count()
    }
).ToListAsync();

AOT Support

Install SQLite.Framework.SourceGenerator and call UseGeneratedMaterializers():

dotnet add package SQLite.Framework.SourceGenerator
using SQLite.Framework.Generated;

var options = new SQLiteOptionsBuilder("app.db")
    .UseGeneratedMaterializers()
    .Build();

The generator writes the row-to-object code at build time, so the trimmer keeps every type used in a Select and there's no per-query reflection. The UseGeneratedMaterializers extension is generated internal per project, so each project that builds queries needs its own reference.

Without the generator, the library still runs under AOT but uses reflection for queries. Make sure the model classes are reachable from the entry assembly so the trimmer keeps them. Full setup on the Source Generator and Native AOT pages.

Contributing

Bug reports and missing-feature requests are welcome.

License

MIT © Nikolay Kostadinov

There are no supported framework assets in this package.

Learn more about Target Frameworks and .NET Standard.

  • .NETStandard 2.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
5.3.0 28 5/12/2026
5.2.0 56 5/9/2026
5.1.0 96 5/3/2026
5.0.3 94 5/1/2026
5.0.2 97 4/29/2026
5.0.1 95 4/29/2026
5.0.0 100 4/29/2026
5.0.0-preview.2 83 4/23/2026
5.0.0-preview.1 70 4/22/2026