UWP 应用程序的 LevelDB





5.00/5 (2投票s)
开始在 UWP 应用程序中使用 LevelDB
引言
LevelDBWinRT
是一个 Windows Runtime 组件,它使你可以在 Windows 10 通用平台 (UWP) 应用程序中使用 LevelDB
。它的设计旨在尽可能地复制 LevelDB
API,让开发者能够完全控制核心 LevelDB
。对于那些不知道 LevelDB
是什么的人来说,它是一个由 Google 编写的快速键值存储库,提供了一个从字符串键到字符串值的有序映射。
本文档将简要介绍如何在 UWP 应用程序中使用 LevelDBWinRT
来开始使用 LevelDB
。
为什么选择 LevelDB?
LevelDB
是一个显而易见且极其快速的键值存储!以下是此运行时组件提供的一些基本功能:
- 键和值可以是任意字节数组(切片)
- 数据按键存储和排序
- 调用者可以提供自定义比较函数来覆盖排序顺序(实验性支持)
- 支持基本的 Get(key)/Put(key, value)/Delete(key) 操作
- 原子批处理操作可以进行多次更改
- 用户可以创建瞬时快照以获取数据的一致视图
- 支持迭代器,支持向前和向后迭代
- 对
WriteOptions
、ReadOptions
、Options
的基本封装 - 内置 Snappy 压缩支持
- 自定义比较器支持(实验性)
- 支持 ARM、x86 和 x64 架构
- 支持 Windows 8 和 WP 8.1
安装
你可以通过在此处 安装 nuget 来安装 LevelDBWinRT。或者,只需在你的 程序包管理器控制台 中运行 Install-Package LevelDB.UWP
。
创建数据库
创建和打开数据库非常简单。所有内容都包含在 LevelDBWinRT
命名空间下,首先使用 using LevelDBWinRT
导入该命名空间。每个数据库对应一个文件,创建数据库意味着创建一个 LevelDB 文件。用于操作数据库的主要类是 LevelDBWinRT.DB
。构造函数接受两个参数 - 第一个参数是创建数据库的选项,第二个参数是文件路径。示例:
var db = new DB(new Options { CreateIfMissing = true }, "foo.db");
这将在 ApplicationData.Current.LocalFolder.Path
下创建名为 foo.db
的数据库文件。如果你不指定文件的完整路径(即,它不以 X:\ 开头,其中 X 是驱动器号),则默认文件夹假定为 ApplicationData.Current.LocalFolder.Path
。如果你没有文件夹访问权限或路径不存在,操作将失败。失败时,将抛出带有捕获的错误代码和错误消息的 COMException
。如果你只想在数据库存在时打开它,否则失败,则移除 CreateIfMissing
选项。在底层,CreateIfMissing
会链接到 leveldb::Options
对象(几乎所有选项都可以供你使用,并且它们功能强大)。我们暂时保持简单,大多数默认选项已经调整得很好。
处置数据库
DB 类是可处置的。因此,调用 Dispose()
实际上会删除底层的 leveldb
对象,进而正确释放内存并关闭对文件的任何打开句柄。因此,一旦你完成了数据库的使用,请务必将其处置掉。
db.Dispose();
不处置数据库对象并丢失对对象的引用会将其留给 GC 进行清理,这可能会产生不良后果,因此请务必正确处置你的对象。
添加和删除条目
数据库打开后,可以轻松地添加和删除其中的条目。要向 LevelDB
添加或删除任何内容,你需要提供切片,一个键切片和一个值切片。在 LevelDB
的术语中,切片只是字节数组的封装。LevelDBWinRT.Slice
是你可以用来从 byte[]
或 string
创建切片的类。尽管 byte[]
足以生成任何类型的切片,但由于 string
的频繁使用,也提供了重载。插入键值对 "foo" => "bar"
就像这样简单:
db.Put(new WriteOptions(), Slice.FromString("foo"), Slice.FromString("bar"));
你可以使用 WriteOptions
来控制是否立即将更改同步到磁盘。删除具有类似的 API,删除 "foo
" 就像这样简单:
db.Delete(new WriteOptions(), Slice.FromString("foo"));
立即将更改刷新到磁盘非常简单,只需在任何写入操作中将 Sync 设置为 true
,例如:
db.Put(new WriteOptions{ Sync = true },
Slice.FromString("foo"), Slice.FromString("bar"));
字节和切片
到目前为止,我们可以看到切片是 LevelDB
的一个组成部分,而字节是切片的一个基本组成部分。这里做出的一项设计选择是只提供两种创建切片的方法。有两种 static
方法:Slice.FromString
和 Slice.FromByteArray
。前者 Slice.FromString
用于频繁操作,后者 Slice.FromByteArray
用于支持几乎所有其他操作。也提供了反向方法 ToByteArray
和 AsString
,用于将值转换回来。你可以使用 BitConverter
和任何类型的对象序列化程序将复杂对象转换为 byte[]
,LevelDB **会尽力不干扰你**,让你自己处理序列化事务。
读取值
读取单个值也非常简单。你可以直接这样做:
Slice slice = db.Get(new ReadOptions(), Slice.FromString("foo"));
string sliceValue = slice.AsString(); // "bar"
ReadOptions
再次公开了一些选项,以让你更精细地控制读取。详细信息将在另一部分讨论。
批次写入
就像任何优秀的数据库一样,LevelDB
提供了在单次写入操作(原子操作)中执行批量插入和删除的选项。可以通过 LevelDB
提供的 WriteBatch
类创建写入批次。你可以像下面这样创建和提交批次:
using (var batch = new WriteBatch())
{
batch.Put(Slice.FromString("foo"), Slice.FromString("bar"));
batch.Delete(Slice.FromString("del"));
db.Write(new WriteOptions(), batch);
}
更复杂的例子可以是:
using(var writeBatch = new WriteBatch())
{
for (var i = 0; i < 10; i++)
{
writeBatch.Put(Slice.FromString("Key"+i), Slice.FromByteArray(BitConverter.GetBytes(i)));
}
db.Write(new WriteOptions(), writeBatch);
}
它还有更高级的功能(迭代器和快照)
还有更多精彩内容。LevelDB
提供了快照和迭代器,它们提供对整个数据库的只读视图。请查看官方 GitHub 仓库 的源代码和详细文档。
下载附带的示例项目,以查看代码的实际运行情况。