Skip to content

Kittyfisto/IsabelDb

Repository files navigation

IsabelDb

Build status

IsabelDb is a key value store which allows you to persist .NET objects on disk and read them back again.
Is is particularly suited for on-disk caches and is intended to be used for long term storage as well, but currently backwards compatibility cannot be guaranteed just yet.

Introduction

The following example gives you a quick introduction into how to use this database:

[DataContract]
public class Document
{
    [DataMember]
    public string Name { get; set; }

    [DataMember]
    public string Content { get; set; }
}

using (var database = IsabelDb.Database.OpenOrCreate("some file path.isdb", new[]{typeof(Document)}))
{
    var cache = database.GetDictionary<int, Document>("Cache");
    cache.Put(42, new Document{Name = "Foo.txt", Content = "..." });
    ....
    if (cache.TryGet(42, out var document))
    {
        Console.WriteLine(document.Content);
    }
}

Installation

Simply head over to nuget.org to download the latest release of IsabelDb or use the following command in the Package Manager Console: Install-Package IsabelDb

Requirements

Currently, IsabelDb targets .NET 4.5.
If you require other targets, such as .NET core , then please let me know.

Quick facts

  • IsabelDb stores all data in a single file on disk
  • A database consists of zero or more collections
  • Each collection can store zero or more objects where each object must be serializable
  • Each operation on a collection is atomic
  • Each mutating operation blocks until its data is flushed to disk
  • Any custom type with a data contract can be stored in the database

Collections

IsabelDb offers several collections which behave similar to their .NET counterpart, but their contents are stored on disk and not in memory. As such, a collection can exceed the size of a process' virtual memory and its computer's physical memory.

Bag

A collection which stores a list of values: Values can be added to the collection and streamed back by iterating over GetAll(). Removing individiual values is not possible (use Dictionary if that's necessary).

var items = database.GetBag<object>("Items");
items.PutMany(new[]{1, 42, "Hello", "World!");
Console.WriteLine(string.Join(", ", items.GetAll()); //< Prints '1, 42, Hello, World!'

Queue

A collection which stores values and allows them to be retrieved in the same order in which they were added (FIFO). You can enqueue, dequeue values as well as peek on the value which would be retrieved next.

var items = database.GetQueue<object>("Tasks");
items.Enqueue("Do your homework");

if (items.TryDequeue(out var nextTask))
   Console.WriteLine("Next task: {0}", nextTask);

Dictionary

A collection which maps values to non-null keys. There can never be more than one value for the same key. If you put a new key / value pair into the collection, then any existing value for that same key will be overwritten:

var items = database.GetDictionary<string, object>("Items");
items.Put("foo", "Hello, World!");
Console.WriteLine(items.Get("foo")); //< Prints 'Hello, World!'
items.Put("foo", 42);
Console.WriteLine(items.Get("foo")); //< Prints '42'

MultiValueDictionary

A collection which maps values to non-null keys: There can be multiple values for the same key. If you put a key / value pair into the collection then that value will be appended to the previous list of values:

var items = database.GetMultiValueDictionary<string, object>("Items");
items.Put("foo", "Hello");
items.Put("foo", "World!");
Console.WriteLine(string.Join(", ", items.Get("foo"))); //< Prints 'Hello, World!'

OrderedCollection

Very similar to a dictionary, but requires its keys to be sortable and allows range queries:

var items = database.GetOrderedCollection<int, object>("Items");
items.Put(1, "Hello");
items.Put(2, "World!");
items.Put(4, "What's up?");
Console.WriteLine(string.Join(", ", items.GetValues(Interval.Create(0, 3))); //< Prints 'Hello, World!'

Defining Serializable Types

IsabelDb works with every custom type if it follows these rules:

  • The type must be marked with the [DataContract] attribute
  • Fields/Properties which are to be serialized must be marked with the [DataMember] attribute
  • The field/property types which are marked with the [DataMember] attribute must themselves be serializable

These rules are pretty much aligned to what Microsoft expects from a data contract. You may head over to docs.microsoft.com for a more detailed explanation.
If you're interested in the limits of serialization in this database, head over to the serialization constraints page for a detailed explanation of what isn't possible.

Backward compatibility

Backward compatibility in this context refers to the ability to:

  • Read data from a database which was written with a previous version
  • Modify data in a database which was written with a previous version

The following list of changes is permitted without breaking backward compatibility:

If you change the name or namespace of a type marked with the [DataContract] attribute, then you should put its old namespace / name in the attribute:

[DataContract(Namespace "OldNamespace", Name = "OldTypeName")] public class NewType {}

If you change the name of a field / property marked with the [DataMember] attribute, then you should put its old name in the attribute:

[DataMember(Name = "OldPropertyName")] public string NewPropertyName { get; set; }

Adding new fields / properties with the [DataMember] attribute.

You can remove fields / properties with the [DataMember] attribute, however if you do so, then you will lose that data upon roundtripping and then reading back the object in an older version.

Forward Compatibility

Forward compatibility in this context refers to the ability to:

  • Read data from a database which was written with a future version
  • Modify data in a database which was written with a future version

Reading data from future versions is no problem (as unknown properties will simply be ignored). Roundtripping objects from future versions will only work without data loss if they inherit from Extensible:

using Protobuf
...
[DataContract]
public class MyFutureProofType : Extensible
{
}

Breaking changes to serializable types

IsabelDb tolerates same changes to the type model, but several changes are considered breaking changes. The following document provides you with a detailed overview of which changes are allowed and which are breaking: Serialization.

About

A .NET key value database to persist objects on disk

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages