Connecting to MongoDB from .NET

In the realm of modern software development, databases play a pivotal role in storing, managing, and retrieving data. Among the plethora of database options available, MongoDB has emerged as a prominent player, particularly in the NoSQL domain. In this article, we will delve into MongoDB, understand its key concepts, and explore how to integrate it seamlessly with C# through multiple examples.

Understanding MongoDB

MongoDB is a widely-used NoSQL database system that falls under the category of document-oriented databases. Unlike traditional relational databases, which use tables and rows to store data, MongoDB employs a flexible structure known as BSON (Binary JSON) documents. These documents can hold a variety of data types and can be nested within each other, providing a rich and versatile way to represent data.

Key Concepts

  1. Collections: In MongoDB, data is organized into collections. A collection is a group of related documents, much like a table in a relational database.

  2. Documents: A document is a set of key-value pairs where the keys are strings and the values can be a variety of data types such as strings, numbers, arrays, and even other documents.

  3. Fields: Fields are the individual data elements within a document, each with its own key and associated value.

  4. Indexes: Indexes in MongoDB are similar to indexes in traditional databases. They improve query performance by allowing for quicker data retrieval.

  5. Query Language: MongoDB provides a powerful query language for searching and retrieving data from collections. The queries are expressed in JSON-like syntax.

Integrating MongoDB with C#

To interact with MongoDB using C#, you can use the official MongoDB C# Driver. This driver provides a comprehensive set of classes and methods to connect to a MongoDB database, perform CRUD (Create, Read, Update, Delete) operations, and work with the data seamlessly.

Example 1: Connecting to MongoDB

Before performing any operations, you need to establish a connection to the MongoDB server. Here's how you can achieve this using the C# driver:

using MongoDB.Driver;

// Define the connection string
string connectionString = "mongodb://localhost:27017";

// Create a MongoClient
var client = new MongoClient(connectionString);

// Access a specific database
var database = client.GetDatabase("mydatabase");

Example 2: Inserting Data

Let's insert a document into a collection named "users":

using MongoDB.Bson;
using MongoDB.Driver;

var userCollection = database.GetCollection<BsonDocument>("users");

// Create a new document
var newUser = new BsonDocument
{
    { "name", "John Doe" },
    { "age", 30 },
    { "email", "john@example.com" }
};

// Insert the document
userCollection.InsertOne(newUser);

Example 3: Querying Data

Now, let's retrieve data from the "users" collection:

var filter = Builders<BsonDocument>.Filter.Eq("name", "John Doe");
var result = userCollection.Find(filter).ToList();

foreach (var user in result)
{
    Console.WriteLine($"name:{user.name} age:{user.age} email:{user.email}");
}

Example 4: Updating Data

Updating documents is straightforward as well:

var filter = Builders<BsonDocument>.Filter.Eq("name", "John Doe");
var update = Builders<BsonDocument>.Update.Set("age", 31);

userCollection.UpdateOne(filter, update);

Example 5: Deleting Data

To remove a document:

var filter = Builders<BsonDocument>.Filter.Eq("name", "John Doe");

userCollection.DeleteOne(filter);

Example 6: Using Strongly Typed models to map MongoDB data

Below is an example of how to connect to MongoDB in .NET using strongly typed models.

Github Link

The code below will first save a list of articles in MongoDB and then retrieve that data by applying some filters.

Step 1. Create a new .NET console project and add the nuget package MongoDB.Driver

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net5.0</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="MongoDB.Driver" Version="2.14.1" />
  </ItemGroup>

</Project>

Step 2. Add a model class to store data to and from MongoDB. We are going to name our class Article

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

namespace BasicMongoDBApp
{
    public class Article
    {

        [BsonId]
        public ObjectId Id { get; set; }

        [BsonElement("title")]
        public string Title { get; set; }

        [BsonElement("author")]
        public string Author { get; set; }

        [BsonElement("content")]
        public string Content { get; set; }

        [BsonElement("views")]
        public int Views { get; set; }

        [BsonElement("upvotes")]
        public int UpVotes { get; set; }

    }
}

Step 3. We will now try to connect to MongoDB. We need to provide valid server, port, and replica name. In return, MongoDB library will provide us with an object of IMongoClient.

using MongoDB.Driver;
using MongoDB.Bson.Serialization.Conventions;
using System.Linq;
using System;

namespace BasicMongoDBApp
{
    class Program
    {
        static void Main(string[] args)
        {
            //MongoDB properties - please provide valid values
            string username = "user_name";  //ignored if connected to localhost
            string password = "password";   //ignored if connected to localhost
            string hostname = "localhost";  //provide server name
            int portNumber = 27017;
            string replicaSet = "mcrypt_01";

            string connectionString = $"mongodb://{username}:{password}@{hostname}:{portNumber}?readPreference=primaryPreferred&replicaSet={replicaSet}&authMechanism=PLAIN&authSource=$external&ssl=true";

            //Setup the connection
            IMongoClient mongoClient = new MongoClient(connectionString);
        }
    }
}

In case your MongoDB service is running in localhost without any username password, then your connection string can be simply this

string connectionString = $"mongodb://localhost:{portNumber}";

Step 4. Now we need to get the database and collection objects from the MongoDB client that we created above. We will specify here that our collection is going to be a collection of Article objects.

IMongoDatabase mongoDatabase = mongoClient.GetDatabase(database);
IMongoCollection<Article> mongoCollection = mongoDatabase.GetCollection<Article>(collectionName);

Step 5. Let's create some data that we can write to our new collection. Below you can see we are creating a list of Articles

private static List<Article> testData = new List<Article>
{
            new Article
            {
                Title = "How to Know Who You Really Are and Aren't", 
                Author = "John Doe", 
                Content = "What are your most important personal values? Do you actually value what you say you do, or are you lying to yourself?", 
                Views = 1000,  
                UpVotes = 200
            },

            new Article
            {
                Title = "Why Facts Don't Change Our Opinions", 
                Author = "John Doe", 
                Content = "Why don't facts change our minds? And why would someone continue to believe a false or inaccurate idea anyway? How do such behaviors serve us?", 
                Views = 1500,  
                UpVotes = 250
            },

            new Article
            {
                Title = "Physicists discover Higgs boson",
                Author = "Jane Doe", 
                Content = "The Higgs boson, discovered at the CERN particle physics laboratory near Geneva, Switzerland, is the particle that gives all other fundamental particles mass",
                Views = 1000,  
                UpVotes = 50
            },
        };
    }
}

Step 6. Let's write the test data into our new collection. We just need to write one line

//write some test data 
mongoCollection.InsertMany(testData);

Above line will insert the data in our Articles collection like shown below

image.png

Step 7. Next, let's try to read the data we just wrote, and fetch a specific record - an article whose Author is John Doe and Views are greater than 1000.

//fetch the data
var records = mongoCollection
               .Find(a => a.Author == "John Doe")
               .ToEnumerable()
               .Where(a => a.Views > 1000);

Step 8. Finally we can print this data on console if we want

//print the records
Console.WriteLine("Showing all articles authored by John Doe with more than 1000 views");
foreach (var article in records)
{
        Console.WriteLine($"Title: {article.Title} | Content: {article.Content}");
}

Step 9. The final code looks like this. You may have noticed that we have added an IgnoreExtraElementsConvention flag. This tells MongoDB to ignore any fields for which there is no mapping in our model class. Without this flag, our code will error out if there is a new field added to the mongo object and our C# class doesn't have the corresponding mapping field.

using MongoDB.Bson;
using MongoDB.Driver;
using MongoDB.Bson.Serialization.Attributes;
using MongoDB.Bson.Serialization.Conventions;
using System.Linq;
using System;

namespace BasicMongoDBApp
{
    public class Article
    {

        [BsonId]
        public ObjectId Id { get; set; }

        [BsonElement("title")]
        public string Title { get; set; }

        [BsonElement("author")]
        public string Author { get; set; }

        [BsonElement("content")]
        public string Content { get; set; }

        [BsonElement("views")]
        public int Views { get; set; }

        [BsonElement("upvotes")]
        public int UpVotes { get; set; }

    }


    class Program
    {
        static void Main(string[] args)
        {
            //MongoDB properties - please provide valid values
            string username = "user_name";  //ignored if connected to localhost
            string password = "password";   //ignored if connected to localhost
            string hostname = "localhost";  //server name
            int portNumber = 27017;
            string database = "mindcrypt";
            string replicaSet = "mcrypt_01";
            string collectionName = "articles";

            string serverConnectionString = $"mongodb://{username}:{password}@{hostname}:{portNumber}?readPreference=primaryPreferred&replicaSet={replicaSet}&authMechanism=PLAIN&authSource=$external&ssl=true";
            string localConnectionString = $"mongodb://localhost:{portNumber}";
            string connectionString = hostname == "localhost" ? localConnectionString : serverConnectionString;

            //Ignore the MongoDB fields that are currently not added to our model yet
            ConventionRegistry.Register(
                "IgnoreExtraElements",
                new ConventionPack { new IgnoreExtraElementsConvention(true) },
                _ => true);

            //Setup the connection
            IMongoClient mongoClient = new MongoClient(connectionString);
            IMongoDatabase mongoDatabase = mongoClient.GetDatabase(database);
            IMongoCollection<Article> mongoCollection = mongoDatabase.GetCollection<Article>(collectionName);

            //write some test data 
            mongoCollection.InsertMany(testData);

            //fetch the data
            var records = mongoCollection
                        .Find(a => a.Author == "John Doe")
                        .ToEnumerable()
                        .Where(a => a.Views > 1000);

            //print the records
            Console.WriteLine("Showing all articles authored by John Doe with more than 1000 views");
            foreach (var article in records)
            {
                Console.WriteLine($"Title: {article.Title} | Content: {article.Content}");
            }
        }

        private static List<Article> testData = new List<Article>
        {
            new Article
            {
                Title = "How to Know Who You Really Are and Aren't", 
                Author = "John Doe", 
                Content = "What are your most important personal values? Do you actually value what you say you do, or are you lying to yourself? And just who the hell are you anyway?", 
                Views = 1000,  
                UpVotes = 200
            },

            new Article
            {
                Title = "Why Facts Don't Change Our Opinions", 
                Author = "John Doe", 
                Content = "Why don't facts change our minds? And why would someone continue to believe a false or inaccurate idea anyway? How do such behaviors serve us?", 
                Views = 1500,  
                UpVotes = 250
            },

            new Article
            {
                Title = "Physicists discover Higgs boson",
                Author = "Jane Doe", 
                Content = "The Higgs boson, discovered at the CERN particle physics laboratory near Geneva, Switzerland, is the particle that gives all other fundamental particles mass",
                Views = 1000,  
                UpVotes = 50
            },
        };
    }
}

Output:

image.png

Conclusion

MongoDB offers a flexible and powerful way to store and manage data, particularly when working with complex or dynamic data structures. The integration of MongoDB with C# using the official MongoDB C# Driver opens up a world of possibilities for developers seeking efficient and scalable solutions for their data storage needs. With this guide and the provided examples, you have a solid foundation to start exploring the combination of MongoDB and C# in your own projects. Happy coding!