### LiteDB

LiteDB ist eine OpenSource (\cite{dbms-litedb-source}) NoSQL Datenbank, welche als eingebettete
Datenbank für eine Dotnet (u.a. auch C#) Anwendung fungiert. Diese ist komplett in C# geschrieben
(\cite{dbms-litedb-home}) und bietet eine große Palette an Funktionen und Anbindungen für Dotnet.

LiteDB speichert seine Daten in einem BSON (Binary JSON) Format. Dieses ist an JSON angelehnt und
soll die Verarbeitung erleichtern. LiteDB nutzt nur ein Subset der vom offiziellen BSON Schema
\cite{bson-schema} unterstützten Datentypen (siehe \cite{dbms-litedb-data-structure}). Das ist
hauptsächlich aus dem Grund, damit sich die Arbeit mit den Erweiterungen, die BSON unterstützt,
erspart wird.

LiteDB erlaubt die Umwandlung von BSON in JSON und anders herum. Zudem hat es Funktionen zur
Serialisierung und Deserialisierung eingebaut, die BSON Daten in C# Objekte und anders herum
überführen. Dies erleichtert dem Entwickler die Arbeit mit dem Daten enorm.

LiteDB verwaltet die Daten in mehreren Collections. Diese sind Listen von einzelnen beliebigen BSON
Einträgen, die iteriert werden können. Die Collections haben alle einen Namen, über diesen diese
abrufbar sind. Zu einer Datenbank können beliebig viele Collections erstellt werden. Die Elemente
einer Collection müssen nicht gleich aufgebaut sein oder dem gleichen Schema folgen. Die Elemente
können beliebig in einer Collection gelöscht, bearbeitet oder hinzugefügt werden.

Um die Suche von bestimmten Einträgen zu erleichtern, gibt es zu jeder Collection eine oder mehrere
Indexe, welche den exakten Wert eines Pfades innerhalb der jeweiligen BSON Objekte abbilden.
Standardmäßig wird ein Index für die Id (`$.Id`, den Wert von `Id` im Wurzelknoten) angelegt. Es
gibt neben einfachen Collections auch Collections für Dateien (es ist möglich, größere binäre Daten
in LiteDB zu hinterlegen) oder Systemcollections für die interne Verwaltung.

\begin{myfigure}{Skip-Listen}{skiplist} \centering
\includegraphics[scale=0.25]{Skip_list.svg.png}
\newline
\begin{footnotesize}
    Ein kurzes Beispiel für eine Skip-Liste mit einer maximalen Tiefe von 4. Quelle: \cite{skip-list-img-ref}
\end{footnotesize}
\end{myfigure}

Die Indexe sind in LiteDB als Skip-Liste (Quelle: \cite{skip-list-ref}) implementiert. Eine
Skip-Liste ist als verkette Liste in mehreren Ebenen aufgebaut, bei der je nach Ebene, bestimmte
Abschnitte übersprungen werden (siehe Beispiel in Abbildung \ref{skiplist}). Dies funktioniert,
indem jedes Element eine bestimmte Höhe hat und je nach Höhe eine dementsprechende Anzahl von
Zeigern. Jeder Zeiger zeigt auf das jeweils nächste Element, was bis in diese Ebene hinein reicht.
Beim Suchen wird dann in der obersten Ebene nach dem passenden Intervall von links (Anfang der
Kette) nach rechts (Ende der Kette) gesucht. Wird das passende Intervall gefunden, so wird in die
darunter liegende Ebene wieder von links nach rechts in dem Intervall geschaut. Das wird so lange
wiederholt, bis der passende Eintrag gefunden wurde. Einfügen funktioniert, indem zuerst die
passende Stelle gesucht und dann eine zufällige Höhe gewählt wird. Löschen aktualisiert die Zeiger
aller Nachbarn.

Um eine Datenbank in LiteDB zu öffnen, ist folgender Befehl notwendig:

```csharp
// Öffnet oder erstellt eine Datenbank mit zusätzlichen Einstellungen
Database = new LiteDatabase(
    // Der ConnectionString enthält alle Informationen, um eine neue
    // Datenbank zu öffnen. Hier werden nach dem Constructor direkt
    // alle Werte festgelegt.
    new ConnectionString
    {
        Filename = "der Pfad zu der Datenbankdatei",
        // das Passwort, falls eins gesetzt wurde. Andernfalls einfach
        // null.
        Password = "pa$$w0rd",
    }
);
// Nun kann über "Database" direkt auf alle Informationen der Datenbank
// zugegriffen werden.
```

Um Daten auszulesen, wird dann eine Collection von der Datenbank abgefragt. Dies geht auch allgemein
ohne C# Typinformationen und der Entwickler erhält die BSON Rohdaten. Für die Entwicklung ist es
aber praktischer, dies direkt in Objekte überführt zu bekommen. Hier wird ein einfaches Beispiel
genutzt. Ausführliches dazu gibt es im Quellcode der Arbeit in
`server/Dacryptero/DB/DBSingleController.cs`.

```csharp
// Beispielklasse für die Daten. Diese wird genutzt, um das Schema für
// eine Collection zu definieren. LiteDB nutzt Reflection, um alle
// Parameter und Typen auszulesen und auszuwerten und versucht dann
// die Daten von BSON in Person oder anders herum zu übertragen.
// Als Programmierer gibt es dazu nichts extra zu beachten.
public class Person
{
    // Id der Person. ObjectId wird von LiteDB bereitgestellt und ist
    // eine 12 Byte große Zahl.
    public ObjectId Id { get; set; }
    // Ein weiteres Feld. In diesem Fall Name. Es können beliebig
    // weitere Felder, Listen oder auch verschachtelte Typen genutzt
    // werden.
    public string Name { get; set; }
}

// Abrufen der Collection der Datenbank. Dazu wird ein C# Typ und der
// Name der Collection übergeben. Falls die Collection noch nicht 
// existiert, so wird diese angelegt. Der C# Typ sagt LiteDB, in
// welchen Schema alle Daten dieser Collection dargestellt werden
// sollen. Um das Umwandeln kümmert sich LiteDB selbst. Falls die
// Roh-BSON Daten verlangt werden, so kann der Typ weggelassen werden
// und es wird eine Collection von BsonDocument zurückgegeben.
var people = Database.GetCollection<Person>("people"); 

// === Hinzufügen der Person ===
// Hier wird zuerst die Person nur mit dem Namen angelegt. Der Name
// wird explizit gesetzt. Die Id wird auf den Standardwert gelassen.
var person = new Person { Name = "Max Mustermann" };
// Die neue Person wird zur Collection hinzugefügt. Um das Umwandeln
// kümmert sich LiteDB selbst. Nach dem Aufruf hat LiteDB automatisch
// den Wert von Id gesetzt.
people.Insert(person);

// Finden aller Personen dessen Name mit Max anfangen.
var peopleWithMax = people.Find(x => x.Name.StartsWith("Max"));

// Finden der ersten Person anhand der Id
var person2 = people.FindById(person.Id);
```

Wie an den Beispielen sehr leicht erkenntlich ist, ist die Nutzung der Datenbank recht leicht und
die Abfragen können direkt im Nutzercode gemacht werden. Das Zusammenbauen einer Abfrage in
textueller Form wie SQL ist nicht notwendig. Für komplexere Aufgaben gibt es weitere Funktionen,
die in der Dokumentation \cite{dbms-litedb-docs} nachzulesen sind.
