C# Sqlite-Net 一款.NET下的性能超高的SQLite操作库

SQLite 已经成为小型数据库的王者,成为构建桌面程序、小型 Web 应用等必不可少的工具。给广大 .NETer 推荐一款 .NET 下的 SQLite 包装库 SQLite-net,非常好用,性能也很棒,支持.net framework 4.6.1+。

项目地址

https://github.com/praeclarum/sqlite-net

使用以下软件包之一:

版本 包裹 描述
NuGet 包 sqlite-net-pcl .NET 标准库
带加密的 NuGet 包 sqlite-net-sqlcipher 具有加密支持
使用 P/Invoke 的 NuGet 包 sqlite-net-static 使用 P/Invokes 到平台提供的 sqlite3 的特殊版本
没有 SQLitePCLRaw 包的 NuGet 包 sqlite-net-base 没有 SQLitePCLRaw 包,因此您可以选择自己的提供程序

SQLite-net 是一个开源的最小库,允许 .NET、.NET Core 和 Mono 应用程序将数据存储在 SQLite 3 数据库中。它最初是为与Xamarin.iOS一起工作而设计的,但后来发展到可以在所有平台(Xamarin.*、.NET、UWP、Azure 等)上工作。

SQLite-net 被设计为一个快速方便的数据库层。它的设计遵循以下目标

  • 非常容易与现有项目集成并在所有 .NET 平台上运行。

  • SQLite 上的薄包装器,快速高效。(这个库不应该是你查询的性能瓶颈。)

  • 安全地执行 CRUD 操作和查询(使用参数)以及以强类型方式检索这些查询的结果的非常简单的方法。

  • 使用您的数据模型而不强迫您更改您的类。(包含一个小的反射驱动 ORM 层。)

NuGet 安装

从 NuGet安装sqlite-net-pcl 。

重要提示:您需要将 NuGet 包添加到.NET Standard 库项目依赖于平台的应用程序项目

源码安装

SQLite-net 全部包含在 1 个文件中(我知道,这很酷吧?)并且很容易添加到您的项目中。只需将SQLite.cs添加到您的项目中,您就可以开始创建表了。可以在SQLiteAsync.cs中找到异步实现。

支持加密

加密一直是 SQLite 的一个重要掣肘,SQLite-net 可以通过 sqlite-net-sqlcipher 支持数据库加密,让你无需再为加密的问题犯愁。

 var options = new SQLiteConnectionString(databasePath, true,key: "password");
 var db = new SQLiteAsyncConnection(options);

简单易用

使用简单的类属性和特性定义表结构,提供了内置的 ORM 支持 和 Linq 查询语法,写起来自然流畅,丝滑无比。

 public class Student
 {
     [PrimaryKey, AutoIncrement]
     public int Id { get; set; }
     public string Name { get; set; }
 }
 
 // 创建数据库
 var db = new SQLiteConnection(databasePath);
 db.CreateTable<Student>();
 // 插入
 var user = new User() { Name = "张三" };
 db.Insert(user);
 // 查询
 var users = db.Table<User>().Where(u => v.Name.StartsWith("张")).ToList();

也可以直接使用 SQL 执行命令和查询,提高性能,增加灵活性。

 db.Execute ("insert into User(Name) values (?)", "李四");
 db.Query<User> ("select * from User where Id = ?", 3);

异步支持

所有的 API 都有异步版本,帮助你提高应用的性能。

 await db.CreateTableAsync<User>();
 await db.InsertAsync(user);
 await db.Table<User>().Where(u => v.Name.StartsWith("张")).ToListAsync();
 await db.ExecuteScalarAsync<int>("select count(*) from User");

示例时间!

请查阅 Wiki 以获得完整的文档

该库包含可用于控制表构造的简单属性。在一个简单的股票程序中,您可以使用:

public class Stock
{
	[PrimaryKey, AutoIncrement]
	public int Id { get; set; }
	public string Symbol { get; set; }
}

public class Valuation
{
	[PrimaryKey, AutoIncrement]
	public int Id { get; set; }
	[Indexed]
	public int StockId { get; set; }
	public DateTime Time { get; set; }
	public decimal Price { get; set; }
}

一旦您在模型中定义了对象,您就可以选择 API。您可以使用调用一次阻塞一个的“同步 API”,也可以使用调用不阻塞的“异步 API”。您可能希望为移动应用程序使用异步 API 以提高响应速度。

这两个 API 在下面的两个部分中进行了解释。

同步API

一旦你定义了你的实体,你可以通过调用自动在你的数据库中生成表CreateTable

// Get an absolute path to the database file
var databasePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "MyData.db");

var db = new SQLiteConnection(databasePath);
db.CreateTable<Stock>();
db.CreateTable<Valuation>();

您可以使用在数据库中插入行Insert。如果该表包含一个自动递增的主键,那么该键的值将在插入后可用:

public static void AddStock(SQLiteConnection db, string symbol) {
	var stock = new Stock() {
		Symbol = symbol
	};
	db.Insert(stock);
	Console.WriteLine("{0} == {1}", stock.Symbol, stock.Id);
}

Update和存在类似的方法Delete

查询数据最直接的方法是使用Table方法。这可以通过 WHERE 子句和/或添加 ORDER BY 子句来使用谓词进行约束:

var query = db.Table<Stock>().Where(v => v.Symbol.StartsWith("A"));

foreach (var stock in query)
	Console.WriteLine("Stock: " + stock.Symbol);

Query您还可以使用以下方法在低级别查询数据库:

public static IEnumerable<Valuation> QueryValuations (SQLiteConnection db, Stock stock) {
	return db.Query<Valuation> ("select * from Valuation where StockId = ?", stock.Id);
}

Query方法的通用参数指定要为每一行创建的对象类型。它可以是您的表类之一,也可以是其公共属性与查询返回的列相匹配的任何其他类。例如,我们可以将上面的查询重写为:

public class Val
{
	public decimal Money { get; set; }
	public DateTime Date { get; set; }
}

public static IEnumerable<Val> QueryVals (SQLiteConnection db, Stock stock) {
	return db.Query<Val> ("select \"Price\" as \"Money\", \"Time\" as \"Date\" from Valuation where StockId = ?", stock.Id);
}

Execute您可以使用该方法执行数据库的低级别更新。

异步API

异步库使用任务并行库 (TPL)。因此,Task对象的正常使用以及asyncawait关键字都适合您。

定义实体后,您可以通过调用自动生成表CreateTableAsync

// Get an absolute path to the database file
var databasePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "MyData.db");

var db = new SQLiteAsyncConnection(databasePath);

await db.CreateTableAsync<Stock>();

Console.WriteLine("Table created!");

您可以使用在数据库中插入行Insert。如果该表包含一个自动递增的主键,那么该键的值将在插入后可用:

var stock = new Stock()
{
	Symbol = "AAPL"
};

await db.InsertAsync(stock);

Console.WriteLine("Auto stock id: {0}", stock.Id);

UpdateAsync和存在类似的方法DeleteAsync

Table使用该方法可以最直接地查询数据。这将返回一个AsyncTableQuery实例,然后您可以添加谓词以通过 WHERE 子句和/或添加 ORDER BY 进行约束。ToListAsync在调用特殊检索方法 - 、FirstAsync或-之一之前,不会物理接触数据库FirstOrDefaultAsync

var query = db.Table<Stock>().Where(s => s.Symbol.StartsWith("A"));

var result = await query.ToListAsync();

foreach (var s in result)
	Console.WriteLine("Stock: " + s.Symbol);

有许多可用的低级方法。也可以直接通过QueryAsync方法查询数据库。InsertAsync除了etc提供的更改操作之外,您还可以发出ExecuteAsync直接在数据库中更改数据集的方法。

另一个有用的方法是ExecuteScalarAsync。这使您可以轻松地从数据库返回标量值:

var count = await db.ExecuteScalarAsync<int>("select count(*) from Stock");

Console.WriteLine(string.Format("Found '{0}' stock items.", count));

手动 SQL

sqlite-net通常用作轻型 ORM(对象关系映射器),使用方法CreateTableTable. 但是,您也可以将其用作手动执行查询的便捷方式。

下面是一个创建表、插入表(使用参数化命令)并在不使用 ORM 功能的情况下查询表的示例。

db.Execute ("create table Stock(Symbol varchar(100) not null)");
db.Execute ("insert into Stock(Symbol) values (?)", "MSFT");
var stocks = db.Query<Stock> ("select * from Stock");

使用 SQLCipher

您可以通过使用sqlite-net-sqlcipher NuGet 包来使用加密数据库。

数据库键在SqliteConnectionString传递给连接构造函数时设置:

var options = new SQLiteConnectionString(databasePath, true,
	key: "password");
var encryptedDb = new SQLiteAsyncConnection(options);

如果您需要设置 pragmas 来控制加密,可以将操作传递给连接字符串:

var options2 = new SQLiteConnectionString (databasePath, true,
	key: "password",
	preKeyAction: db => db.Execute("PRAGMA cipher_default_use_hmac = OFF;"),
	postKeyAction: db => db.Execute ("PRAGMA kdf_iter = 128000;"));
var encryptedDb2 = new SQLiteAsyncConnection (options2);

谢谢!

感谢 .NET 社区支持这个项目,并感谢所有帮助使这个项目变得伟大的贡献者。

还要感谢 Tirza van Dijk (@tirzavdijk) 提供的精美徽标!

posted @   多见多闻  阅读(8654)  评论(0编辑  收藏  举报
(评论功能已被禁用)
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
点击右上角即可分享
微信分享提示