-
Notifications
You must be signed in to change notification settings - Fork 4
01. Getting Started
LevelDBWinRT is a Windows Runtime component which enables you to use LevelDB in you Windows 8.1, Windows Phone 8.1, and Windows 10 Universal Platform (UWP). It's designed to replicate the LevelDB API as close as possible giving developer full control over core LevelDB. For those who don't know what LevelDB is, it's a fast key-value storage library written at Google that provides an ordered mapping from string keys to string values.
This document gives you a brief overview for getting started with LevelDB in UWP application using the LevelDBWinRT.
Install the NuGet package (available on nuget.org) from https://www.nuget.org/packages/LevelDB.UWP.
Make sure you choose x86, x64, or ARM once you install the package.
Any CPU
configuration won't work.
Creating and opening database is really simple. Everything lives under LevelDBWinRT namespace, import the namespace first by using LevelDBWinRT
. Each database corresponds to few files (imagine it unique file for now), creating a database means creating set of LevelDB storage files. The primary class for manipulating a database is LevelDBWinRT.DB
. The constructor takes two parameters first one is options to create database, the second one is the file path. Example:
var db = new DB(new Options { CreateIfMissing = true }, "foo.db");
This creates database foo.db
under ApplicationData.Current.LocalFolder.Path
, if you don't specify full path to the file (i.e. it doesn't start with X:\ where X is drive letter) the default folder is assumed to be ApplicationData.Current.LocalFolder.Path
. The operation will fail if you don't have access on the folder or your path does not exist. In case of failure a COMException
is thrown with captured error code and error message.
If you want to only open database if it exists and fail otherwise remove CreateIfMissing
option. Under the hood CreateIfMissing
is hooked up to leveldb::Options.create_if_missing object
; you will see almost all leveldb::Options
properties existing in LevelDBWinRT.Options
(with some additional options). We will keep it simple for now; most of default options are by default tuned for a good balance.
The DB class is disposable. So calling Dispose()
actually deletes the underlaying LevelDB object, which in turn properly releases non-managed memory, and closes any opened handles to the files. So once you are done using a database be sure to dispose it off.
db.Dispose();
Once database has been opened one can easily add and remove entries to it. To add or remove anything from LevelDB you need to provide slices. A key slice and a value slice, slices are nothing but a wrapper around byte array in LevelDB. LevelDBWinRT.Slice
is the class you can use to create slices from byte[]
or string
. Although byte[]
is enough for generating any type of slice, string
overloads have been provided keeping too frequent usage in mind. Inserting a key-value pair "foo" -> "bar" is as simple as:
db.Put(new WriteOptions(), Slice.FromString("foo"), Slice.FromString("bar"));
You can use WriteOptions
to control if you want to Sync changes to disc right away or not. Delete has similar API, deleting "foo" is as simple as:
db.Delete(new WriteOptions(), Slice.FromString("foo"));
Flushing changes to disk immediately is pretty simple just set Sync to true, example:
db.Put(new WriteOptions{ Sync = true }, Slice.FromString("foo"), Slice.FromString("bar"));
By now you can see Slices are integral part of LevelDB and bytes are fundamental part of slice. One of the design choices made here is to only provide two methods to create a Slice Slice.FromString
and Slice.FromByteArray
. Slice.FromString
for being too common, and Slice.FromByteArray
to support vitally anything. Reverse methods are also available ToByteArray
and AsString
(in spirit of sticking close to C# from v1.18+ this method has been renamed to ToString
) to convert values back. You can use BitConverter
and any sort of object serializers to convert your complex objects to byte[]
, LevelDB just stays out of your way and lets you take care of serialization business.
Reading individual values is also pretty simple. You can simply do:
Slice slice = db.Get(new ReadOptions(), Slice.FromString("foo"));
string sliceValue = slice.AsString(); // "bar"
ReadOptions
again exposes few options to give you more control over your read. Details will be discussed in a different section.
Just like any good database LevelDB provides options to do batch inserts and deletes in a single write operation (Atomic). A write batch can be created by WriteBatch
class provided by LevelDB. You can create and commit a batch as following:
using (var batch = new WriteBatch())
{
batch.Put(Slice.FromString("foo"), Slice.FromString("bar"));
batch.Delete(Slice.FromString("del"));
db.Write(new WriteOptions(), batch);
}
A more complex example can be:
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 { Sync = true }, writeBatch);
}
There is more than meets the eyes. LevelDB has snapshots and iterators that provide read-only views to entire database. Checkout detailed documentation to digg further into documentation.
Download Sample Project to try out working example.