前言
做 .NET / Unity / Xamarin 开发,只要涉及到本地数据存储,SQLite 几乎是绕不开的选择。
但直接用 ADO.NET 写 SQLite 操作?代码量大、参数绑定繁琐、结果集映射全靠手写——体验相当原始。
有没有一个库,能让你像操作普通对象一样操作数据库,不需要 Entity Framework 那样重的框架,上手即用、一点不拖沓?
sqlite-net 正是这个问题的答案。
它有多简洁?核心代码只有 1 个文件,2000 多行。安装后,在任何 .NET 项目里加几行属性标注,就可以直接对数据库进行 CRUD 操作,连 SQL 都可以不用写。
sqlite-net 是什么
sqlite-net 是一个极简 SQLite ORM 库,由知名 .NET 开源开发者 praeclarum 创建和维护(GitHub @praeclarum)。
最初为 Xamarin.iOS 项目设计,后来扩展到支持所有 .NET 平台:
.NET / .NET Core / .NET Framework Mono / Xamarin.iOS / Xamarin.Android UWP / WinRT Unity Azure
项目地址:
https://github.com/praeclarum/sqlite-net
安装方式直接通过 NuGet:
# 标准版
dotnet add package sqlite-net-pcl
# 支持加密(SQLCipher)
dotnet add package sqlite-net-sqlcipher
# 使用平台内置 SQLite(P/Invoke)
dotnet add package sqlite-net-static
# 不含 SQLite 驱动(自行选择 provider)
dotnet add package sqlite-net-base核心特性
特性一:极简集成——整个库只有 1 个源文件
sqlite-net 的核心哲学是**"不强迫你改变已有类"**。
不需要继承任何基类,不需要实现任何接口,只需要在属性上打几个标记,框架自动完成建表、CRUD 操作:
publicclassStock
{
[PrimaryKey, AutoIncrement]
publicint Id { get; set; }
publicstring Symbol { get; set; }
}
publicclassValuation
{
[PrimaryKey, AutoIncrement]
publicint Id { get; set; }
[Indexed]
publicint StockId { get; set; }
public DateTime Time { get; set; }
publicdecimal Price { get; set; }
[Ignore]
publicstring IgnoreField { get; set; } // 不存入数据库
}
常用属性标注说明:
[PrimaryKey] | |
[AutoIncrement] | |
[Indexed] | |
[Unique] | |
[Ignore] | |
[MaxLength(n)] | |
[NotNull] |

特性二:同步 / 异步双 API 支持
移动端推荐使用异步 API,避免阻塞主线程;桌面端两种方式均可。
同步 API:
var db = new SQLiteConnection("stock.db");
db.CreateTable<Stock>();
var stock = new Stock { Symbol = "AAPL" };
db.Insert(stock);
Console.WriteLine($"Inserted, Id = {stock.Id}");
var query = db.Table<Stock>().Where(s => s.Symbol.StartsWith("A"));
foreach (var s in query)
Console.WriteLine(s.Symbol);
异步 API(移动端推荐):
var db = new SQLiteAsyncConnection("stock.db");
await db.CreateTableAsync<Stock>();
var stock = new Stock { Symbol = "AAPL" };
await db.InsertAsync(stock);
var result = await db.Table<Stock>().Where(s => s.Symbol.StartsWith("A")).ToListAsync();
特性三:强类型查询——告别 DataReader
传统 ADO.NET 查询结果要手动从 DataReader 读字段、转型、赋值——繁琐且容易出错。
sqlite-net 直接返回强类型的 List,字段自动映射到对象属性:
// 强类型查询
var query = db.Table<Stock>().Where(s => s.Symbol.StartsWith("A"));
var result = await query.ToListAsync();
// 底层 SQL 查询也可以强类型接收
var vals = db.Query<Valuation>("SELECT * FROM Valuation WHERE StockId = ?", stockId);
特性四:加密数据库支持
使用 sqlite-net-sqlcipher 包,可以轻松接入加密版 SQLite(基于 SQLCipher):
var options = new SQLiteConnectionString(databasePath, true,
key: "your-password");
var encryptedDb = new SQLiteAsyncConnection(options);
也支持设置加密参数(通过 PRAGMA):
var options = new SQLiteConnectionString(dbPath, true,
key: "password",
preKeyAction: db => db.Execute("PRAGMA cipher_default_use_hmac = OFF;"),
postKeyAction: db => db.Execute("PRAGMA kdf_iter = 128000;"));
特性五:LINQ 风格查询
// 链式 LINQ 查询
var results = db.Table<Stock>()
.Where(s => s.Symbol.StartsWith("A"))
.OrderBy(s => s.Symbol)
.Skip(10)
.Take(20)
.ToList();
// 或者直接写 SQL 也不反对
var raw = db.Query<Stock>("SELECT * FROM Stock WHERE Symbol LIKE ?", "A%");
快速上手
第一步:安装 NuGet 包
dotnet add package sqlite-net-pcl
注意:需要同时在主程序项目和共享库项目中都添加引用。
第二步:定义数据模型
publicclassTodoItem
{
[PrimaryKey, AutoIncrement]
publicint Id { get; set; }
publicstring Title { get; set; }
publicbool IsDone { get; set; }
public DateTime CreatedAt { get; set; }
}
第三步:创建数据库连接
var dbPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "todo.db");
var db = new SQLiteAsyncConnection(dbPath);
await db.CreateTableAsync<TodoItem>();
第四步:CRUD 操作
// 插入
var item = new TodoItem { Title = "学习 sqlite-net", IsDone = false, CreatedAt = DateTime.Now };
await db.InsertAsync(item);
// 查询
var all = await db.Table<TodoItem>().ToListAsync();
var done = await db.Table<TodoItem>().Where(x => x.IsDone).ToListAsync();
// 更新
item.IsDone = true;
await db.UpdateAsync(item);
// 删除
await db.DeleteAsync(item);
整个过程不需要写一行 SQL——除非你想写。
API 用法详解
建表
// 同步
db.CreateTable<Stock>();
// 异步
await db.CreateTableAsync<Stock>();
插入
// 单条插入,自增主键会自动回填
await db.InsertAsync(new Stock { Symbol = "AAPL" });
// 批量插入
await db.InsertAllAsync(listOfStocks);
// 如果主键冲突则替换
await db.InsertOrReplaceAsync(stock);
查询
// 查询全部
var all = await db.Table<Stock>().ToListAsync();
// 条件查询(强类型 Lambda)
var aapl = await db.Table<Stock>().Where(s => s.Symbol == "AAPL").FirstOrDefaultAsync();
// 分页
var page = await db.Table<Stock>().OrderBy(s => s.Id).Skip(0).Take(10).ToListAsync();
// 聚合查询
var count = await db.ExecuteScalarAsync<int>("SELECT COUNT(*) FROM Stock");
更新和删除
// 更新(实体必须有主键)
await db.UpdateAsync(stock);
// 按条件更新
await db.ExecuteAsync("UPDATE Stock SET Symbol = ? WHERE Id = ?", "MSFT", 1);
// 删除
await db.DeleteAsync(stock);
// 按条件删除
await db.ExecuteAsync("DELETE FROM Stock WHERE Id < ?", 100);
高级用法
手动执行 SQL
sqlite-net 并不限制你写 SQL,实际上它是一个很好的"轻量 SQL 执行器":
// 建表
db.Execute("CREATE TABLE IF NOT EXISTS Stock(Symbol TEXT NOT NULL)");
// 插入(参数化查询,防注入)
db.Execute("INSERT INTO Stock(Symbol) VALUES (?)", "MSFT");
// 查询结果映射到强类型
var stocks = db.Query<Stock>("SELECT * FROM Stock WHERE Symbol LIKE ?", "M%");
跨平台存储路径
// 各平台正确路径
string dbPath;
// .NET Standard / Mono
dbPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "app.db");
// Unity (iOS)
dbPath = Path.Combine(Application.persistentDataPath, "app.db");
// UWP
dbPath = Path.Combine(Windows.Storage.ApplicationData.Current.LocalFolder.Path, "app.db");
sqlite-net 适用场景
非常适合:
✅ 移动端(Xamarin / Unity)本地数据持久化 ✅ 小型桌面工具软件的数据存储 ✅ 快速原型开发,不需要 EF 那样的重量框架 ✅ 已有 .NET 项目需要轻量本地数据库 ✅ 不想写 SQL,又需要强类型安全保障的开发
不适合(建议用 EF Core):
❌ 需要复杂的关系映射(一对多、多对多) ❌ 需要数据库迁移管理(Migrations) ❌ 需要跨多个数据库(SQL Server / PostgreSQL 切换) ❌ 需要完整的 ORM 特性(懒加载、级联等)
结尾
sqlite-net 是一个定位非常清晰的项目:做 SQLite 的轻量 ORM,而不是另一个 Entity Framework。
它不试图做太多事情——没有迁移系统、没有关系图谱、没有复杂的查询构建器。只是让你能用最少的代码,把对象存进 SQLite,再取出来。
整个库只有 1 个核心源文件(SQLite.cs),代码质量高、逻辑清晰,非常适合作为学习 ORM 设计思路的参考。
作者 praeclarum 是 .NET 社区的资深贡献者,除了 sqlite-net 还维护了多个知名开源项目。
GitHub:
https://github.com/praeclarum/sqlite-net
如果对你有帮助,欢迎 ⭐ Star 支持!