🕓 4 MIN References, Tools, Frameworks …
This article will look closely at LiteDB, a .NET NoSQL Document Store in a single data file. We will discover the advantages of LiteDB and why it is a viable candidate for your next project.
We will also explore the differences between a NoSQL and a classical SQL database and what this has to do with the reminiscent SQL CE or the more modern SQLite database.
Lastly, we will develop a sample .NET WebApp using Uno Platform and LiteDB.
LiteDB is a document store that gets saved into a single file. That means that all your data resides in a single file. If you remember the good old times’ citation needed, you might remember SQL Server Compact, a single file database based on the SQL Server. A modern version would be SQLite, which is also a single-file database. All of them are serverless, meaning you don’t need to install anything additional, which runs in a background thread and does all the work. This simplicity enables a wide variety of scenarios (especially for rapid prototyping).
Some more points, which are listed on their GitHub page:
Serverless NoSQL Document Store
Simple API, similar to MongoDB
100% C# code for .NET 4.5 / NETStandard 1.3/2.0 in a single DLL (less than 450kb)
Thread-safe
ACID with full transaction support
Data recovery after write failure (WAL log file)
Datafile encryption using DES (AES) cryptography
Map your POCO classes to BsonDocument using attributes or fluent mapper API
Store files and stream data (like GridFS in MongoDB)
Single data file storage (like SQLite)
Index document fields for fast search
LINQ support for queries
SQL-Like commands to access/transform data
LiteDB Studio – Nice UI for data access
Open source (❤️)and free for everyone – including commercial use
These are perfect preconditions to try it out and use it right away because we don’t have to set up anything. So now you might ask yourself, What would be typical use cases for this?
Mobile Apps (Xamarin ready)
Desktop/local applications
Application file format
Smaller web applications
One database per account/user data store
If you checked out the LiteDB website, you often see NoSQL, which almost sounds like SQL, so before deep diving into code, we should clarify what these two terms mean.
NoSQL stands for not only SQL. That means, in contrast to SQL, which stands for structured query language, NoSQL stores in a more dynamic way. It not only means that we can also use SQL language to ask for data, but there are also other ways. Traditionally SQL databases store data in a relational structure, mainly in tables with columns, which then can refer to other tables. In the case of LiteDB, we store the data in documents. Documents are roughly JSON objects. Each document contains pairs of keys and their corresponding values.
So if we have a C# object like this:
public class BlogPost
{
public string Title { get; set; }
public string Content { get; set; }
public bool IsPublished { get; set; }
public string List Tags { get; set; }
}
Then a typical document representing that data in a document database could look like this:
{
"Title": "LiteDB - A .NET embedded NoSQL database",
"Content": "This article contains a lot of information.",
"IsPublished": true,
"Tags": [
".NET",
"NoSQL",
"LiteDB"
]
}
Now the same in a traditional table and column-based SQL database wouldn’t be that easy to model. Every 1 to n relationship has to be modified with a new table and foreign key relations. As the document database are “loose” in terms of structure we had no trouble modelling this, plus the structure mirrors our “real C#” entity.
Of course we simplify here a bit. On top we most probable have a unique identifier and some metadata about the object in question, but these are more details than we need right now. Hopefully you can see that it’s super easy to get hierarchical data we have in our application. Everything is concise together in one object.
We can now use this power to build Uno Platform apps. You might remember that we already could do something similar with SQLite: Working with SQLite and WebAssembly for .NET Developers. This article describes how to use SQLite with the Uno Platform. And guess what: We can do something similar with LiteDB as well. So let’s do it. If you did not set up Uno Platform on your developer machine, head to the Get Started guide. Yes, you read right, we can also use LiteDB inside the browser, giving the user an easy possibility to persist state! That is awesome! Here is what we are going for:
So let’s create a new Uno Platform app. I am a big fan of the command line arguments, but you can also take the Visual Studio Project templates. To create a new app you can simply type: dotnet new unoapp-uwp-net6 -o LiteDBSample
(the template allows also for optionally removing some Uno Platform heads: dotnet new unoapp-uwp-net6 -o LiteDBSample -M=false -skia-wpf=false -skia-gtk=false -skia-linux-fb=false
. With this you are only running the WASM head). Don’t worry you can also take other templates if you wish, as the code will work everywhere. Now if we want to use LiteDB, we have to reference the nuget package in your Uno HeadWhat is a Head? projects:
dotnet add package LiteDB --version 5.0.12
Or alternatively just copy and paste this part into your csproj:
With that out of the way, we are only working in the Shared project, and more specific in the MainPage-component, from now on. The full source code is at the end, so I will only show some key elements. The small app, as shown in the picutre, can hold some todo items for you. So we need a way to insert those items from the users point of view:
The important bit here is the AddTodoItem
function. This will add the todo item to our LiteDB:
private void AddTodoItem(object sender, RoutedEventArgs args)
{
// Create the domain object from the text box
var todoItem = new TodoItem
{
Text = todoText.Text
};
// Clear the model for the user
todoText.Text = string.Empty;
// Create a new LiteDb and insert the item
var liteDatabase = new LiteDatabase(DbPath);
var liteCollection = liteDatabase.GetCollection();
liteCollection.Insert(todoItem);
liteCollection.Commit();
_todoItems.Add(todoItem);
}
A bit more explanation: var liteDatabase = new LiteDatabase(DbPath);
will either create and open a file with the given path (in this case DbPath
which is just Path.Combine(ApplicationData.Current.LocalFolder.Path, "save.db");
) or just read the file if it already exists. So we don’t have to take care of much here. liteDatabase.GetCollection<TodoItem>();
will give us the collection of objects, which are represented in our database. If you ever worked with Entity Framework the LiteDatabase
object is your DbContext
and GetCollection<TodoItem>
represents your DbSet<TodoItem>
on said DbContext
. After that we insert the record and commit the transaction. Commit
would translate to SaveChanges
in Entity Framework. The last line adds the Todo-item in our in memory representation (an observable list) so the user directly sees a result.
Another small aspect I want to show in the application is this part:
Here we load those entries from the database into the in memory collection.
private void LoadFromDatabase(object sender, RoutedEventArgs args)
{
var liteDatabase = new LiteDatabase(DbPath);
var liteCollection = liteDatabase.GetCollection();
var todoItems = liteCollection
.FindAll()
.ToList();
_todoItems.Clear();
todoItems.ForEach(t => _todoItems.Add(t));
}
FindAll
is basically a ToList
on the whole collection. That is very basic. The neat thing is that we can use also LINQ with LiteDB.
var todoItems = liteDatabase.GetCollection().Query();
var itemsWhichShouldBeDoneByToday =
(from item in todoItems
where !item.IsDone && item.DeadLine <= DateTime.Now
select item).ToList();
Of course you can also use the method chaining instead of the query language. The core idea is, that Query()
returns you a IQueryable
, which let’s you use all the power of LINQ and friends. And there you have it, the easy and rapid power of LiteDB paired with the easiness and power of the Uno Platform.
One thing you might have noticed until now: All the methods I used are synchrnous. There is no await liteDatabase.GetCollection<TodoItem>().ToListAsync()
or friends. You should consider the asynchrnous paradigm. If you have a regular desktop application or even the WASM head, async
makes sense, as it doesn’t block the UI thread. LiteDB itself doesn’t offer asynchrnous operations, but there is a community project, which does that: litedb-async.
As initially said, there is also a LiteDB Studio. With this UI tool, you can submit queries to your “database.” If you come from a SQL world, you can use all your well-known SQL queries, and they are still working with LiteDB. Unfortunately, there is one significant disadvantage at the moment: The studio runs only under Windows. The reason is simple: First, it runs under the .NET Framework 4.7.2, which is only supported by Windows, and second, it is a WinForms application.
For those new to Uno Platform – it allows for creation of pixel-perfect, single-source C# and XAML apps which run natively on Windows, iOS, Android, macOS, Linux and Web via WebAssembly. Uno Platform is free and Open Source (Apache 2.0) and available on GitHub.
I hope I could give you a nice introduction to LiteDB and why it is a viable candidate for your next project.
To upgrade to the latest release of Uno Platform, please update your packages to 4.6 via your Visual Studio NuGet package manager! If you are new to Uno Platform, following our official getting started guide is the best way to get started. (5 min to complete)
Authored by Steven Giesel
🕓 4 MIN References, Tools, Frameworks …
Uno Platform
360 rue Saint-Jacques, suite G101,
Montréal, Québec, Canada
H2Y 1P5
USA/CANADA toll free: +1-877-237-0471
International: +1-514-312-6958
Necessary cookies are absolutely essential for the website to function properly. This category only includes cookies that ensures basic functionalities and security features of the website. These cookies do not store any personal information.
Any cookies that may not be particularly necessary for the website to function and is used specifically to collect user personal data via analytics, ads, other embedded contents are termed as non-necessary cookies. It is mandatory to procure user consent prior to running these cookies on your website.
Uno Platform 5.2 LIVE Webinar – Today at 3 PM EST – Watch