Connecting a .NET Application to MongoDB

Melah GhislainMelah Ghislain
7 min read

MongoDB is a NoSQL database that is widely used for building modern applications due to its flexibility and scalability. In this blog, we will walk through the process of connecting a .NET application to MongoDB and performing CRUD operations. We'll use the code from a project that manages suggestions for improvements in an application.

Prerequisites

  • Install .NET SDK

  • MongoDB installed locally or available through a cloud service such as MongoDB Atlas

  • MongoDB .NET Driver installed through NuGet

Step 1: Install MongoDB Driver in Your .NET Project

To begin, ensure you have MongoDB.Driver installed in your project. You can do this by running the following command in the terminal:

dotnet add package MongoDB.Driver

This installs the official MongoDB .NET driver, which provides tools to interact with MongoDB.

Step 2: Define the MongoDB Connection Interface

In any well-structured application, it’s good practice to define interfaces for database connections to ensure abstraction and easier maintainability. Here's how the interface for MongoDB connection is structured in this project:

namespace SuggestionAppLibrary.Interfaces
{
    public interface IDbConnection
    {
        string DbName { get; }
        string CategoryCollectionName { get; }
        string StatusCollectionName { get; }
        string UserCollectionName { get; }
        string SuggestionCollectionName { get; }
        MongoClient Client { get; }
        IMongoCollection<CategoryModel> CategoryCollection { get; }
        IMongoCollection<StatusModel> StatusCollection { get; }
        IMongoCollection<UserModel> UserCollection { get; }
        IMongoCollection<SuggestionModel> SuggestionCollection { get; }
    }
}

This interface defines key elements such as collection names and the client connection for MongoDB. Each collection in MongoDB will represent a different dataset like Categories, Statuses, Users, and Suggestions.

Step 3: Defining Models with MongoDB BSON Attributes

MongoDB works with documents, and in this application, a suggestion has various fields such as a description, creation date, author, and status.

When working with MongoDB in .NET, you’ll need to create model classes that map to MongoDB collections. MongoDB uses BSON (Binary JSON) as its storage format. To ensure that your C# models map correctly to MongoDB documents, you can use BSON attributes provided by the MongoDB.Bson library.

Here is the SuggestionModel that defines how each suggestion is structured:

using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;

public class SuggestionModel
{
    [BsonId]  // Marks 'Id' as the document identifier
    [BsonRepresentation(BsonType.ObjectId)]  // Ensures 'Id' is stored as an ObjectId
    public string Id { get; set; }

    [BsonElement("suggestionText")]  // Maps 'Suggestion' to 'suggestionText' field
    public string Suggestion { get; set; }

    [BsonElement("description")]  // Maps 'Description' to 'description' field
    public string Description { get; set; }

    [BsonElement("dateCreated")]  // Maps 'DateCreated' to 'dateCreated' field
    [BsonDateTimeOptions(Kind = DateTimeKind.Utc)]  // Ensures date is stored in UTC
    public DateTime DateCreated { get; set; } = DateTime.UtcNow;

    [BsonElement("category")]  // Maps 'Category' to 'category' field
    public CategoryModel Category { get; set; }

    [BsonElement("author")]  // Maps 'Author' to 'author' field
    public UserModel Author { get; set; }

    [BsonElement("userVotes")]  // Maps 'UserVotes' to 'userVotes' field
    public HashSet<string> UserVotes { get; set; } = new();

    [BsonElement("status")]  // Maps 'SuggestionStatus' to 'status' field
    public StatusModel SuggestionStatus { get; set; }

    [BsonElement("ownerNotes")]  // Maps 'OwnerNotes' to 'ownerNotes' field
    public string OwnerNotes { get; set; }

    [BsonElement("approvedForRelease")]  // Maps 'ApprovedForRelease' to 'approvedForRelease' field
    public bool ApprovedForRelease { get; set; } = false;

    [BsonElement("archived")]  // Maps 'Archived' to 'archived' field
    public bool Archived { get; set; } = false;

    [BsonElement("rejected")]  // Maps 'Rejected' to 'rejected' field
    public bool Rejected { get; set; } = false;
}

Each field is annotated with BSON attributes to map the C# object to the MongoDB document structure.

Common BSON Properties

  1. [BsonId]

    • Marks the property as the document ID. In MongoDB, every document must have a unique identifier, which is commonly the _id field.
  2. [BsonRepresentation(BsonType.ObjectId)]

  • This attribute specifies that the Id field will be stored as a MongoDB ObjectId type, even though it is represented as a string in the model.
  1. [BsonElement("elementName")]
  • Maps a property to a specific BSON element (field) in the MongoDB document. The elementName parameter represents the field name in the MongoDB document.

  • This is useful if the property name in the model is different from the field name in MongoDB.

  1. [BsonIgnoreIfNull]
  • Tells MongoDB to ignore this field if it is null. This can help avoid unnecessary storage in the database.
  1. [BsonIgnore]
  • Prevents a property from being serialized or deserialized. The field won’t be saved in MongoDB, nor will it be populated when reading documents from MongoDB.
  1. [BsonDateTimeOptions]
  • This decorator controls how DateTime values are stored in MongoDB. For example, you can specify whether the DateTime should be treated as UTC or Local.
  1. [BsonDefaultValue(defaultValue)]
  • Specifies a default value for a field if it is not set when the document is created.
  1. [BsonRequired]
  • Ensures that the field must be present in the document when it is deserialized from MongoDB. If the field is missing, an exception will be thrown.

Step 4: Implementing the Repository Pattern

To ensure proper abstraction, this project uses the repository pattern. A repository for SuggestionModel is responsible for interacting with the MongoDB collections. Here's a snippet of the SuggestionRepo class that interacts with the Suggestion collection:

public class SuggestionRepo : ISuggestion
{
    private readonly IMongoCollection<SuggestionModel> _suggestions;
    private readonly IMemoryCache _cache;
    private const string CacheName = "SuggestionData";

    public SuggestionRepo(IDbConnection db, IMemoryCache cache)
    {
        _suggestions = db.SuggestionCollection;
        _cache = cache;
    }

    public async Task<List<SuggestionModel>> GetAllSuggestions()
    {
        var cachedSuggestions = _cache.Get<List<SuggestionModel>>(CacheName);
        if (cachedSuggestions == null)
        {
            var suggestions = await _suggestions.FindAsync(s => !s.Archived);
            cachedSuggestions = suggestions.ToList();
            _cache.Set(CacheName, cachedSuggestions, TimeSpan.FromMinutes(1));
        }
        return cachedSuggestions;
    }

    // Additional CRUD methods...
}

This class handles various operations such as retrieving all suggestions, filtering approved suggestions, and caching the data to reduce load on the database.

Step 5: Setting Up MongoDB Configuration

To establish a connection to MongoDB, you will need to configure your application. Typically, this is done in the DbConnection.cs file, which you provided. Here's an example of how the connection configuration might look:

using Microsoft.Extensions.Configuration;

namespace SuggestionAppLibrary.DataAccess;

public class DbConnection : IDbConnection
{
    private readonly IConfiguration _config;
    private readonly IMongoDatabase _db;
    private string _connectionId = "MongoDb";

    public string DbName { get; private set; }

    public string CategoryCollectionName { get; private set; } = "categories";
    public string StatusCollectionName { get; private set; } = "statuses";
    public string UserCollectionName { get; private set; } = "users";
    public string SuggestionCollectionName { get; private set; } = "suggestions";

    public MongoClient Client { get; private set; }

    public IMongoCollection<CategoryModel> CategoryCollection { get; private set; }
    public IMongoCollection<StatusModel> StatusCollection { get; private set; }
    public IMongoCollection<UserModel> UserCollection { get; private set; }
    public IMongoCollection<SuggestionModel> SuggestionCollection { get; private set; }

    public DbConnection(IConfiguration config)
    {
        _config = config;

        Client = new MongoClient(_config.GetConnectionString(_connectionId));
        DbName = _config["DatabaseName"];

        _db = Client.GetDatabase(DbName);

        CategoryCollection = _db.GetCollection<CategoryModel>(CategoryCollectionName);
        StatusCollection = _db.GetCollection<StatusModel>(StatusCollectionName);
        UserCollection = _db.GetCollection<UserModel>(UserCollectionName);
        SuggestionCollection = _db.GetCollection<SuggestionModel>(SuggestionCollectionName);
    }
}

In this class, the MongoDB client is initialized using a connection string from the configuration file (appsettings.json), which you can define as follows:

{
  "ConnectionStrings": {
    "MongoDB": "mongodb://localhost:27017"
  },
  "DatabaseName": "SuggestionAppDB"
}

Make sure to replace the connection string with your MongoDB instance details.

Step 6: Register Services in the .NET Application

You need to register the services in your Program.cs or Startup.cs. This will ensure the repository and database connection services are available throughout the application.

public static class RegisterServices
{
    public static void ConfigureServices(this WebApplicationBuilder builder)
    {
        builder.Services.AddRazorPages();
        builder.Services.AddServerSideBlazor();
        builder.Services.AddMemoryCache();

        // Register MongoDB services
        builder.Services.AddSingleton<IDbConnection, DbConnection>();
        builder.Services.AddSingleton<ISuggestion, SuggestionRepo>();
    }
}

Step 7: Performing CRUD Operations

Now that your application is connected to MongoDB, you can perform CRUD operations. For example, here is how you can retrieve suggestions:

public async Task<List<SuggestionModel>> GetAllSuggestions()
{
    var suggestions = await _suggestions.FindAsync(s => !s.Archived);
    return suggestions.ToList();
}

And here’s how to insert a new suggestion:

public async Task CreateSuggestion(SuggestionModel suggestion)
{
    await _suggestions.InsertOneAsync(suggestion);
}

Conclusion

By following the steps in this guide, you have successfully set up a MongoDB connection in a .NET application and performed basic CRUD operations. This setup allows you to efficiently work with MongoDB and leverage its flexibility in your application development process. You can now expand on this foundation by adding more complex logic or improving your database structure based on your app's requirements.

1
Subscribe to my newsletter

Read articles from Melah Ghislain directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Melah Ghislain
Melah Ghislain

Full Stack Developer | Building Scalable Applications with Typescript, JavaScript and C# I am a Full Stack Developer with over 3+ years of experience crafting high-quality, user-centric web applications. Proficient in a wide range of technologies, including React, Node.js, C#/.NET, MongoDB, and PostgreSQL, I focus on building scalable and high-performance solutions. My passion lies in creating intuitive user interfaces and optimizing code to deliver seamless user experiences. I enjoy working in Agile environments and collaborating with cross-functional teams to bring innovative ideas to life. I’m fluent in both English and French, and I continuously seek opportunities to learn and contribute to open-source projects. When I'm not coding, I work on personal projects, exploring creative ways to solve real-world problems through technology