MongoDB C# Driver

Integrate MongoDB with .NET applications seamlessly

🔷 What is MongoDB C# Driver?

The MongoDB C# Driver provides native .NET integration for MongoDB databases. It offers strongly-typed collections, LINQ support, and async/await patterns, making it perfect for modern .NET applications with full IntelliSense support and compile-time safety.


// Simple C# connection
using MongoDB.Driver;

var client = new MongoClient("mongodb://localhost:27017");
var database = client.GetDatabase("myDatabase");
Console.WriteLine("Connected to MongoDB!");
                                    

Key Features

🎯

LINQ Support

Query with familiar LINQ syntax

Where Select OrderBy

Async/Await

Full asynchronous operation support

Task-based Non-blocking Scalable
🔒

Type Safety

Strongly-typed collections and models

Generic Types IntelliSense Compile-time
🏗️

.NET Integration

Native .NET framework support

.NET Core .NET 6+ ASP.NET

🔹 NuGet Installation

Install the MongoDB C# Driver via NuGet Package Manager. This package includes all necessary libraries for connecting to MongoDB and performing database operations with full .NET integration and IntelliSense support.

# Package Manager Console
Install-Package MongoDB.Driver

# .NET CLI
dotnet add package MongoDB.Driver

🔹 Connecting to MongoDB

Create a connection using MongoClient with connection strings. The driver automatically manages connection pooling and provides thread-safe access to databases and collections with full async support.

using MongoDB.Driver;

public class MongoDBService
{
    private readonly IMongoClient _client;
    private readonly IMongoDatabase _database;
    
    public MongoDBService()
    {
        // Create connection
        _client = new MongoClient("mongodb://localhost:27017");
        
        // Get database
        _database = _client.GetDatabase("myDatabase");
        
        Console.WriteLine("Connected successfully!");
    }
    
    public IMongoCollection<T> GetCollection<T>(string name)
    {
        return _database.GetCollection<T>(name);
    }
}

🔹 Define Models

Create C# classes to represent MongoDB documents with attributes for field mapping. Use BsonElement to map property names and BsonId for the document identifier, ensuring seamless serialization between C# objects and BSON.

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

public class User
{
    [BsonId]
    [BsonRepresentation(BsonType.ObjectId)]
    public string Id { get; set; }
    
    [BsonElement("name")]
    public string Name { get; set; }
    
    [BsonElement("email")]
    public string Email { get; set; }
    
    [BsonElement("age")]
    public int Age { get; set; }
    
    [BsonElement("hobbies")]
    public List<string> Hobbies { get; set; }
    
    [BsonDateTimeOptions(Kind = DateTimeKind.Local)]
    public DateTime CreatedAt { get; set; }
}

🔹 Insert Documents

Add documents to collections using strongly-typed models. The driver provides InsertOneAsync for single documents and InsertManyAsync for bulk inserts, both returning detailed results about the operation.

var collection = _database.GetCollection<User>("users");

// Insert one document
var user = new User
{
    Name = "John Doe",
    Email = "[email protected]",
    Age = 30,
    Hobbies = new List<string> { "reading", "coding" },
    CreatedAt = DateTime.Now
};

await collection.InsertOneAsync(user);
Console.WriteLine($"Inserted ID: {user.Id}");

// Insert multiple documents
var users = new List<User>
{
    new User { Name = "Alice", Email = "[email protected]", Age = 25 },
    new User { Name = "Bob", Email = "[email protected]", Age = 35 }
};

await collection.InsertManyAsync(users);
Console.WriteLine($"Inserted {users.Count} documents");

Output:

Inserted ID: 507f1f77bcf86cd799439011

Inserted 2 documents

🔹 Find Documents with LINQ

Query collections using familiar LINQ syntax for intuitive data retrieval. The driver translates LINQ expressions into MongoDB queries, providing compile-time type checking and IntelliSense support for your queries.

var collection = _database.GetCollection<User>("users");

// Find all documents
var allUsers = await collection.Find(_ => true).ToListAsync();
foreach (var user in allUsers)
{
    Console.WriteLine(user.Name);
}

// Find with LINQ filter
var adults = await collection
    .Find(u => u.Age >= 18)
    .ToListAsync();

// Find one document
var user = await collection
    .Find(u => u.Name == "John Doe")
    .FirstOrDefaultAsync();
Console.WriteLine($"Found: {user?.Name}");

// Find with projection
var names = await collection
    .Find(_ => true)
    .Project(u => new { u.Name, u.Email })
    .ToListAsync();

// Using LINQ AsQueryable
var youngUsers = collection.AsQueryable()
    .Where(u => u.Age < 30)
    .OrderBy(u => u.Name)
    .ToList();

Output:

John Doe

Found: John Doe

🔹 Update Documents

Modify documents using the Builders class for type-safe update operations. The driver supports various update operators and provides detailed results including the number of documents matched and modified.

var collection = _database.GetCollection<User>("users");

// Update one document
var filter = Builders<User>.Filter.Eq(u => u.Name, "John Doe");
var update = Builders<User>.Update
    .Set(u => u.Age, 31)
    .Set(u => u.Email, "[email protected]");

var result = await collection.UpdateOneAsync(filter, update);
Console.WriteLine($"Modified: {result.ModifiedCount}");

// Update many documents
var filterMany = Builders<User>.Filter.Lt(u => u.Age, 30);
var updateMany = Builders<User>.Update.Set(u => u.Status, "young");

var multiResult = await collection.UpdateManyAsync(filterMany, updateMany);
Console.WriteLine($"Updated: {multiResult.ModifiedCount}");

// Increment a value
var incUpdate = Builders<User>.Update.Inc(u => u.Age, 1);
await collection.UpdateOneAsync(filter, incUpdate);

// Add to array
var pushUpdate = Builders<User>.Update.Push(u => u.Hobbies, "gaming");
await collection.UpdateOneAsync(filter, pushUpdate);

Output:

Modified: 1

Updated: 2

🔹 Delete Documents

Remove documents from collections using DeleteOneAsync or DeleteManyAsync. The driver returns detailed results including the count of deleted documents, allowing you to verify the operation's success.

var collection = _database.GetCollection<User>("users");

// Delete one document
var filter = Builders<User>.Filter.Eq(u => u.Name, "John Doe");
var result = await collection.DeleteOneAsync(filter);
Console.WriteLine($"Deleted: {result.DeletedCount}");

// Delete many documents
var filterMany = Builders<User>.Filter.Lt(u => u.Age, 18);
var multiResult = await collection.DeleteManyAsync(filterMany);
Console.WriteLine($"Deleted: {multiResult.DeletedCount}");

// Delete all documents
var deleteAll = await collection.DeleteManyAsync(_ => true);
Console.WriteLine($"All deleted: {deleteAll.DeletedCount}");

Output:

Deleted: 1

Deleted: 3

🔹 Aggregation Pipeline

Build complex aggregation pipelines using the fluent API with strongly-typed stages. Combine multiple operations like matching, grouping, and sorting to perform sophisticated data analysis directly in MongoDB.

var collection = _database.GetCollection<User>("users");

// Aggregation pipeline
var results = await collection.Aggregate()
    .Match(u => u.Age >= 18)
    .Group(
        u => u.City,
        g => new
        {
            City = g.Key,
            AvgAge = g.Average(u => u.Age),
            Count = g.Count()
        }
    )
    .SortByDescending(r => r.AvgAge)
    .ToListAsync();

foreach (var result in results)
{
    Console.WriteLine($"{result.City}: avg {result.AvgAge}, count {result.Count}");
}

Output:

New York: avg 32, count 5

Boston: avg 28, count 3

🔹 Dependency Injection

Integrate MongoDB with ASP.NET Core's dependency injection system. Register MongoClient as a singleton service for efficient connection management and inject it into your controllers or services.

// In Program.cs or Startup.cs
using MongoDB.Driver;

builder.Services.AddSingleton<IMongoClient>(sp =>
{
    var connectionString = builder.Configuration.GetConnectionString("MongoDB");
    return new MongoClient(connectionString);
});

builder.Services.AddScoped(sp =>
{
    var client = sp.GetRequiredService<IMongoClient>();
    return client.GetDatabase("myDatabase");
});

// In your controller or service
public class UserService
{
    private readonly IMongoCollection<User> _users;
    
    public UserService(IMongoDatabase database)
    {
        _users = database.GetCollection<User>("users");
    }
    
    public async Task<List<User>> GetAllUsersAsync()
    {
        return await _users.Find(_ => true).ToListAsync();
    }
}

🔹 Error Handling

Implement comprehensive error handling using MongoDB's exception types. Catch specific exceptions for different scenarios like connection failures, duplicate keys, or timeout issues to build resilient .NET applications.

using MongoDB.Driver;

try
{
    var client = new MongoClient("mongodb://localhost:27017");
    var database = client.GetDatabase("myDB");
    var collection = database.GetCollection<User>("users");
    
    var user = new User
    {
        Name = "Test User",
        Email = "[email protected]",
        Age = 25
    };
    
    await collection.InsertOneAsync(user);
    Console.WriteLine("Operation successful");
}
catch (MongoWriteException ex) when (ex.WriteError.Category == ServerErrorCategory.DuplicateKey)
{
    Console.WriteLine($"Duplicate key error: {ex.Message}");
}
catch (MongoConnectionException ex)
{
    Console.WriteLine($"Connection error: {ex.Message}");
}
catch (MongoException ex)
{
    Console.WriteLine($"MongoDB error: {ex.Message}");
}
catch (Exception ex)
{
    Console.WriteLine($"General error: {ex.Message}");
}

🧠 Test Your Knowledge

What attribute is used to mark the ID property in a C# model?