ASP.NET Core Blog tutorial: using LiteDB
Tags: dotnet, webdev, csharp, tutorial
Published: 2019-11-30 11:57:43

## NoSQL with LiteDB 
Welcome back. In this part of the tutorial series we'll be covering storing and displaying our post data in NoSQL. Specifically we'll be using [LiteDB](https://www.litedb.org/). Why LiteDB? Because it's simple, fast lightweight and easy to understand for all skill levels.

First thing's first we obviously have to install the LiteDB nuget package.
open up a command prompt or terminal emulator in your project folder and run:
```bash
dotnet add package LiteDB
```

## Setting up LiteDB
Create a new folder inside of your models folder and name it `Repos` (short for repositories), inside of that folder create a new file named `BlogRepo.cs`. This class will serve as the default repository, in it we'll store all of our posts for now and maybe some more collections later.

Let's open up the file and create a new repo class

```csharp
using System;
using LiteDB;
using System.Collections.Generic; // Required for using collections such as List

namespace Blog.Models.Repos{
    public class BlogRepo{
        public LiteDatabase DB {get;set;}
        public LiteCollection<Post> Posts {get;set;}
        
        public BlogRepo() {
            DB = new LiteDatabase(@"Data/Blog.db");
            Posts = DB.GetCollection<Post>("posts");
        }
    }
}
```
And that's all you need to create the database in question. Now let's create a new folder named Data in the root of our project directory, this is where all of our database files will be stored.

Let's go into our `HomeController.cs` and add
```csharp
using Blog.Models.Repos;
```

Then let's initialize the repo class in our Index action method with:
```csharp
public IActionResult Index(){
    BlogRepo blogRepo = new BlogRepo();
    return View();
}
```

If we run our asp.net blog application now and go to http://localhost:5000/ we'll see that a new file named `Blog.db` has been automatically created in our Data folder. However much like me before my coffee, it is completely empty and useless. **Remove the repo initialization** from our Index action and let's go back to our `BlogRepo.cs` class.

## Sample Data
For the purposes of this tutorial we'll be creating some sample data and storing it in our newly created database file. To achieve this simply create a new method in the `BlogRepo.cs` class named `CreateExamplePosts` 

```csharp
public void CreateExamplePosts(){
            
            List<Post> PostList = new List<Post>(){
                new Post(){
                    Title = "First post",
                    Public = true,
                    CoverImagePath = "", // leave this blank for now
                    Excerpt = "Define the underlying",
                    Content = "Define the underlying principles that drive decisions and strategy for your design language bleeding edge onward and upward"
                    // The above text was generated by Office Ipsum http://officeipsum.com/index.php
                },
                new Post(){
                    Title = "Second post",
                    Public = true,
                    CoverImagePath = "", // still blank
                    Excerpt = "so what's our",
                    Content = "so what's our go to market strategy?. Customer centric all hands on deck yet where the metal hits the meat define"
                },
                new Post(){
                    Title = "Not visible",
                    Public = false,
                    CoverImagePath = "", // blank
                    Excerpt = "not important",
                    Content = "not important, you should not see this post"
                },
                new Post(){
                    Title = "Third post",
                    Public = true,
                    CoverImagePath = "", // blank
                    Excerpt = "the underlying",
                    Content = "the underlying principles that drive decisions and strategy for your design language not the long pole",
                    Deleted = true // this one should also not be visible
                },
                new Post(){
                    Title = "Fourth post",
                    Public = true,
                    CoverImagePath = "", // blank
                    Excerpt = "in the future",
                    Content = "Post scheduling made super easy",
                    Created = DateTime.Now.AddDays(3) // Post scheduling made easy
                }
            };
            try{
                // This will ensure that the title of the post is unique
                // since we're going to be using it later in the URL
                Posts.EnsureIndex(p => p.Title, true); 

                Posts.EnsureIndex(p => p._id, true); 
                // Finally let's insert all these posts into the database
                Posts.InsertBulk(PostList);
            }catch(LiteDB.LiteException ex){
                // we'll simply ignore any exceptions that might happen here for now
            }
        }
```

Everything up there should be pretty self explanatory, except perhaps for the post that is scheduled for the future. For the purposes of this tutorial I've made it always default to `DateTime.Now.AddDays(3)` which means that you'll be able to see the post 3 days after you first called the `CreateExamplePosts()` method. Obviously I do not expect you to wait that long, if you wish to see it work you can simply change the `AddDays(3)` part to  `AddMinutes(x)` x being the number of minutes you are willing to wait.

The try catch at the end ensures that if you accidentally run this method multiple times it won't show an ugly exception page telling you that the title index has to be unique and there can be no duplicate titles. Which is what we've set by calling
```csharp
Posts.EnsureIndex(p => p.Title, true); 
```
Okay, so if you run your asp.net blog application now, nothing about your database will change because we never really called the method itself. If you wish to ensure that the example data is always available you can call this method from your `Startup.cs` class or you can simply throw it in the `Index` action of our `HomeController` class like such:

```csharp
public IActionResult Index(){
            BlogRepo blogRepo = new BlogRepo();
            blogRepo.CreateExamplePosts();
            return View();
            );
        }
```
Run the application once, then delete the `blogRepo.CreateExamplePosts();` part. Unless you wish for it to try and add our example data every time you or your user visits the root of your blog page.

## Displaying The Blog Posts
Okay so now that our database is filled with example data let's actually try and display it.
Remember the 
```csharp
return View();
```
part of our HomeController's index action? Well, it can take multiple parameters such as
`string viewName` which tells it where to look for the razor html file to display
`object model` which tells it what data to pass to said razor html file.

Change the `return View();` part to
```csharp
return View(blogRepo.Posts.Find(
            p => p.Public == true && 
            p.Created <= DateTime.Now && 
            p.Deleted == false)
        );
```
What we are doing here is calling a LiteDB method that allows us to find all the results from the collection that fit certain parameters. The query is fairly simple and self explanatory but let's go through it just in case.

- `p => ` the => or the lambda operator separates input parameters from the lambda body.
- `p.Public == true` specifies a condition that has to be met by the data we're looking for, in this case the field `Public` of the model `Post` has to be set to true.
- `&&` simply means we wish to specify an additional condition
- `p.Created <= DateTime.Now && ` the field `Created` of the model `Post`  has to be smaller than `<` or equal to `=` `DateTime.Now`
- `p.Deleted == false` the field `Deleted` of the model `Post` has to be false


So in other words we are asking the method `.Find()` to find all posts who are public, were posted either before this exact moment or at this exact moment and are not soft deleted.

Simple enough to understand right?

Aaaaand if we run our ASP.NET blog application nothing will really change, that is because we still need to tell our razor view how to display the data that we've just set it.

## The View
No, still not the show.
Open up our `Index.cshtml` file inside of our `Views/Home` folder and add a new section to the bottom of it like this:
```html
<section class="posts">
	@foreach (var post in Model){
        <div class="post">
            <h2>@post.Title</h2>
            <p>@post.Excerpt</p>
            <a href="@post.Title.Replace(' ','-')">read more</a>
        </div>
    }
</section>
```

Rebuild and run your ASP.NET blog application and you should see 2 of the posts that we've created as part of our example data.
This means everything worked out great!
Now as you can see we've added `<a href="@post.Title.Replace(' ','-')">read more</a>` this will be useful in our next tutorial where we'll be setting up individual views for our Posts.

If you have any questions or issues feel free to contact me at [@arctekdev](https://twitter.com/arctekdev)