LevelDB 是一个由 Google 开发的快速键值存储库,它提供了一个从字符串键到字符串值的有序映射。本文将向您介绍如何在 Windows 10 Universal Platform (UWP) 应用中使用 LevelDBWinRT 来实现 LevelDB 的功能。
LevelDB 提供了以下基本特性:
您可以通过 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 选项。
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 来控制是否立即将更改同步到磁盘。删除 "foo" 也很简单:
db.Delete(new WriteOptions(), Slice.FromString("foo"));
立即将更改刷新到磁盘非常简单,只需在任何写操作中将 Sync 设置为 true,例如:
db.Put(new WriteOptions{ Sync = true }, Slice.FromString("foo"), Slice.FromString("bar"));
到目前为止,可以看到切片是 LevelDB 的一个重要部分,字节是切片的基本部分。这里的一个设计选择是只提供两种方法来创建切片。有两种静态方法,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 提供了在单个写操作中执行批量插入和删除的选项(原子操作)。WriteBatch 类由 LevelDB 提供,您可以创建并提交一个批次,如下所示:
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); }