BlogAtlas Vector Search voted most loved vector database in 2024 Retool State of AI reportLearn more >>
MongoDB Developer
C#
plus
Sign in to follow topics
MongoDB Developer Centerchevron-right
Developer Topicschevron-right
Languageschevron-right
C#chevron-right

MongoDB Provider for EF Core Tutorial: Building an App with CRUD and Change Tracking

Luce Carter18 min read • Published Nov 21, 2023 • Updated Jan 24, 2024
.NETC#
Facebook Icontwitter iconlinkedin icon
Rate this tutorial
star-empty
star-empty
star-empty
star-empty
star-empty
Entity Framework (EF) has been part of .NET for a long time (since .NET 3.51) and is a popular object relational mapper (ORM) for many applications. EF has evolved into EF Core alongside the evolution of .NET. EF Core supports a number of different database providers and can now be used with MongoDB with the help of the MongoDB Provider for Entity Framework Core.
In this tutorial, we will look at how you can build a car booking application using the new MongoDB Provider for EF Core that will support create, read, update, and delete operations (CRUD) as well as change tracking, which helps to automatically update the database and only the fields that have changed.
A car booking system is a good example to explore the benefits of using EF Core with MongoDB because there is a need to represent a diverse range of entities. There will be entities like cars with their associated availability status and location, and bookings including the associated car.
As the system evolves and grows, ensuring data consistency can become challenging. Additionally, as users interact with the system, partial updates to data entities — like booking details or car specifications — will happen more and more frequently. Capturing and efficiently handling these updates is paramount for good system performance and data integrity.

Prerequisites

In order to follow along with this tutorial, you are going to need a few things:
If you just want to see example code, you can view the full code in the GitHub repository.

Create the project

ASP.NET Core is a very flexible web framework, allowing you to scaffold out different types of web applications that have slight differences in terms of their UI or structure. For this tutorial, we are going to create an MVC project that will make use of static files and controllers. There are other types of front end you could use, such as React, but MVC with .cshtml views is the most commonly used. To create the project, we are going to use the .NET CLI:
Because we used the CLI, although easier, it only creates the csproj file and not the solution file which allows us to open it in Visual Studio, so we will fix that.

Add the NuGet packages

Now that we have the new project created, we will want to go ahead and add the required NuGet packages. Either using the NuGet Package Manager or using the .NET CLI commands below, add the MongoDB MongoDB.EntityFrameworkCore and Microsoft.EntityFrameworkCore packages.
At the time of writing, the MongoDB.EntityFrameworkCore is in preview, so if using the NuGet Package Manager UI inside Visual Studio, be sure to tick the “include pre-release” box or you won’t get any results when searching for it.

Create the models

Before we can start implementing the new packages we just added, we need to create the models that represent the entities we want in our car booking system that will of course be stored in MongoDB Atlas as documents. In the following subsections, we will create the following models:
  • Car
  • Booking
  • MongoDBSettings

Car

First, we need to create our car model that will represent the cars that are available to be booked in our system.
  1. Create a new class in the Models folder called Car.
  2. Add the following code:
The collection attribute before the class tells the application what collection inside the database we are using. This allows us to have differing names or capitalization between our class and our collection should we want to.

Booking

We also need to create a booking class to represent any bookings we take in our system.
  1. Create a new class inside the Models folder called Booking.
  2. Add the following code to it:

MongoDBSettings

Although it won’t be a document in our database, we need a model class to store our MongoDB-related settings so they can be used across the application.
  1. Create another class in Models called MongoDBSettings.
  2. Add the following code:

Setting up EF Core

This is the exciting part. We are going to start to implement EF Core and take advantage of the new MongoDB Provider. If you are used to working with EF Core already, some of this will be familiar to you.

CarBookingDbContext

  1. In a location of your choice, create a class called CarBookingDbContext. I placed it inside a new folder called Services.
  2. Replace the code inside the namespace with the following:
If you are used to EF Core, this will look familiar. The class extends the DbContext and we create DbSet properties that store the models that will also be present in the database. We also override the OnModelCreating method. You may notice that unlike when using SQL Server, we don’t call .ToTable(). We could call ToCollection instead but this isn’t required here as we specify the collection using attributes on the classes.

Add connection string and database details to appsettings

Earlier, we created a MongoDBSettings model, and now we need to add the values that the properties map to into our appsettings.
  1. In both appsettings.json and appsettings.Development.json, add the following new section:
  2. Replace the Atlas URI with your own connection string from Atlas.

Updating program.cs

Now we have configured our models and DbContext, it is time to add them to our program.cs file.
After the existing line builder.Services.AddControllersWithViews();, add the following code:

Creating the services

Now, it is time to add the services we will use to talk to the database via the CarBookingDbContext we created. For each service, we will create an interface and the class that implements it.

ICarService and CarService

The first interface and service we will implement is for carrying out the CRUD operations on the cars collection. This is known as the repository pattern. You may see people interact with the DbContext directly. But most people use this pattern, which is why we are including it here.
  1. If you haven’t already, create a Services folder to store our new classes.
  2. Create an ICarService interface and add the following code for the methods we will implement:
  3. Create a CarService class file.
  4. Update the CarService class declaration so it implements the ICarService we just created:
  5. This will cause a red squiggle to appear underneath ICarService as we haven’t implemented all the methods yet, but we will implement the methods one by one.
  6. Add the following code after the class declaration that adds a local CarBookingDbContext object and a constructor that gets an instance of the DbContext via dependency injection.
  7. Next, we will implement the GetAllCars method so add the following code:
    The id property here maps to the _id field in our document which is a special MongoDB ObjectId type and is auto-generated when a new document is created. But what is useful about the _id property is that it can actually be used to order documents because of how it is generated under the hood.
    If you haven’t seen it before, the AsNoTracking() method is part of EF Core and prevents EF tracking changes you make to an object. This is useful for reads when you know no changes are going to occur.
  8. Next, we will implement the method to get a specific car using its Id property:
    Then, we will add the AddCar implementation:
    In a production environment, you might want to use something like ILogger to track these changes rather than printing to the console. But this will allow us to clearly see that a new entity has been added, showing change tracking in action.
  9. EditCar is next:
    Again, we add a call to print out information from change tracking as it will show that the new EF Core Provider, even when using MongoDB as the database, is able to track modifications.
  10. Finally, we need to implement DeleteCar:

IBookingService and BookingService

Next up is our IBookingService and BookingService.
  1. Create the IBookingService interface and add the following methods:
  2. Create the BookingService class, and replace your class with the following code that implements all the methods:
This code is very similar to the code for the CarService class but for bookings instead.

Adding them to Dependency Injection

The final step for the services is to add them to the dependency injection container.
Inside Program.cs, add the following code after the code we added there earlier:

Creating the view models

Before we implement the front end, we need to add the view models that will act as a messenger between our front and back ends where required. Even though our application is quite simple, implementing the view model is still good practice as it helps decouple the pieces of the app.

CarListViewModel

The first one we will add is the CarListViewModel. This will be used as the model in our Razor page later on for listing cars in our database.
  1. Create a new folder in the root of the project called ViewModels.
  2. Add a new class called CarListViewModel.
  3. Add public IEnumerable<Car> Cars { get; set; } inside your class.

CarAddViewModel

We also want a view model that can be used by the Add view we will add later.
  1. Inside the ViewModels folder, create a new class called CarAddViewModel.
  2. Add public Car? Car { get; set; }.

BookingListViewModel

Now, we want to do something very similar for bookings, starting with BookingListViewModel.
  1. Create a new class in the ViewModels folder called BookingListViewModel.
  2. Add public IEnumerable<Booking> Bookings { get; set; }.

BookingAddViewModel

Finally, we have our BookingAddViewModel.
Create the class and add the property public Booking? Booking { get; set; } inside the class.

Adding to _ViewImports

Later on, we will be adding references to our models and viewmodels in the views. In order for the application to know what they are, we need to add references to them in the _ViewImports.cshtml file inside the Views folder.
There will already be some references in there, including TagHelpers, so we want to add references to our .Models and .ViewModels folders. When added, it will look something like below, just with your application name instead.

Creating the controllers

Now we have the backend implementation and the view models we will refer to, we can start working toward the front end. We will be creating two controllers: one for Car and one for Booking.

CarController

The first controller we will add is for the car.
  1. Inside the existing Controllers folder, add a new controller. If using Visual Studio, use the MVC Controller - Empty controller template.
  2. Add a local ICarService object and a constructor that fetches it from dependency injection:
  3. Depending on what your scaffolded controller came with, either create or update the Index function with the following:
    For the other CRUD operations — so create, update, and delete — we will have two methods for each: one is for Get and the other is for Post.
  4. The HttpGet for Add will be very simple as it doesn’t need to pass any data around:
  5. Next, add the Add method that will be called when a new car is requested to be added:
  6. Now, we will add the code for editing a car:
  7. Finally, we have Delete:

BookingController

Now for the booking controller. This is very similar to the CarController but it has a reference to both the car and booking service as we need to associate a car with a booking. This is because at the moment, the EF Core Provider doesn’t support relationships between entities so we can relate entities in a different way. You can view the roadmap on the GitHub repo, however.
  1. Create another empty MVC Controller called BookingController.
  2. Paste the following code replacing the current class:

Creating the views

Now we have the back end and the controllers prepped with the endpoints for our car booking system, it is time to implement the views. This will be using Razor pages. You will also see reference to classes from Bootstrap as this is the CSS framework that comes with MVC applications out of the box. We will be providing views for the CRUD operations for both listings and bookings.

Listing Cars

First, we will provide a view that will map to the root of /Car, which will by convention look at the Index method we implemented.
ASP.NET Core MVC uses a convention pattern whereby you name the .cshtml file the name of the endpoint/method it uses and it lives inside a folder named after its controller.
  1. Inside the Views folder, create a new subfolder called Car.
  2. Inside that Car folder, add a new view. If using the available templates, you want Razor View - Empty. Name the view Index.
  3. Delete the contents of the file and add a reference to the CarListViewModel at the top @model CarListViewModel.
  4. Next, we want to add a placeholder for the error handling. If there was an issue deleting a car, we added a string to TempData so we want to add that into the view, if there is data to display.
  5. Next, we will handle if there are no cars in the database, by displaying a message to the user:
  6. The easiest way to display the list of cars and the relevant information is to use a table:
    It makes sense to have the list of cars as our home page so before we move on, we will update the default route from Home to /Car.
  7. In Program.cs, inside app.MapControllerRoute, replace the pattern line with the following:
If we ran this now, the buttons would lead to 404s because we haven’t implemented them yet. So let’s do that now.

Adding cars

We will start with the form for adding new cars.
  1. Add a new, empty Razor View inside the Car subfolder called Add.cshtml.
  2. Before adding the form, we will add the model reference at the top, a header, and some conditional content for the error message.
  3. Now, we can implement the form.
Now, we want to add a button at the bottom to easily navigate back to the list of cars in case the user decides not to add a new car after all. Add the following after the </form> tag:

Editing cars

The code for the Edit page is almost identical to Add, but it uses the Car as a model as it will use the car it is passed to pre-populate the form for editing.
  1. Add another view inside the Car subfolder called Edit.cshtml.
  2. Add the following code:

Deleting cars

The final page we need to implement is the page that is called when the delete button is clicked for a car.
  1. Create a new empty View called Delete.cshtml.
  2. Add the following code to add the model, heading, and conditional error message:
    Instead of a form like in the other views, we are going to add a description list to display information about the car that we are confirming deletion of.


  3. Below that, we will add a form for submitting the deletion and the button to return to the list:

Listing bookings

We have added the views for the cars so now we will add the views for bookings, starting with listing any existing books.
  1. Create a new folder inside the Views folder called Booking.
  2. Create a new empty view called Index.
  3. Add the following code to display the bookings, if any exist:

Adding bookings

Adding bookings is next. This view will be available when the book button is clicked next to a listed car.
  1. Create an empty view called Add.cshtml.
  2. Add the following code:

Editing bookings

Just like with cars, we also want to be able to edit existing books.
  1. Create an empty view called Edit.cshtml.
  2. Add the following code:

Deleting bookings

The final view we need to add is to delete a booking. As with cars, we will display the booking information and deletion confirmation.
If you want to view the full solution code, you can find it in the GitHub Repo.

Testing our application

We now have a functioning application that uses the new MongoDB Provider for EF Core — hooray! Now is the time to test it all and visit our endpoints to make sure it all works.
It is not part of this tutorial as it is not required, but I chose to make some changes to the site.css file to add some color. I also updated the _Layout.cshtml file to add the Car and Bookings pages to the navbar. You will see this reflected in the screenshots in the rest of the article. You are of course welcome to make your own changes if you have ideas of how you would like the application to look.

Cars

Below are some screenshots I took from the app, showing the features of the Cars endpoint.
List of cars in the garage with their details and action buttons to edit, delete and book
Form for adding a new car
Form for updating a specific vehicle
Deletion confirmation page showing details of car to be deleted

Bookings

The bookings pages will look very similar to cars but are adapted for the bookings model that includes dates.
List of bookings and actions to taken against them
Editing form for an existing booking

Conclusion

There we have it: a full stack application using ASP.NET MVC that takes advantage of the new MongoDB Provider for EF Core. We are able to do the CRUD operations and track changes. EF Core is widely used amongst developers so having an official MongoDB Provider is super exciting. This library is in Preview, which means we are continuing to build out new features. Stay tuned for updates and we are always open to feedback. We can’t wait to see what you build!
You can view the Roadmap of the provider in the GitHub repository, where you can also find links to the documentation!
As always, if you have any questions about this or other topics, get involved at our MongoDB Community Forums.

Facebook Icontwitter iconlinkedin icon
Rate this tutorial
star-empty
star-empty
star-empty
star-empty
star-empty
Related
Article

How to Use Realm Effectively in a Xamarin.Forms App


Oct 19, 2022 | 18 min read
Quickstart

Build Your First .NET Core Application with MongoDB Atlas


Jun 04, 2024 | 6 min read
Tutorial

Using LINQ to Query MongoDB in a .NET Core Application


Jun 10, 2024 | 6 min read
Tutorial

Saving Data in Unity3D Using PlayerPrefs


Sep 07, 2022 | 11 min read
Table of Contents