Implementing MongoDB with .NET

Set up MongoDB in a .NET Web API project and learn the core database and collection operations such as create, insert, update, delete, and count.

Implementing MongoDB with .NET cover

Introduction

In this article, we will implement basic MongoDB operations using .NET and C#. The sample uses the MongoDB.Driver package and keeps everything inside controllers rather than introducing a layered architecture.

In This Article

  • What is MongoDB?
  • Configure MongoDB in a .NET application
  • Understand MongoDB database operations
  • Understand MongoDB collection operations

What Is MongoDB?

MongoDB is a flexible database that stores information in a way that is easy to read and use. It can handle different data shapes without requiring a fixed schema, which makes it useful for websites, apps, and other systems that manage large amounts of data.

Configuring MongoDB in a .NET Application

Step 1: Install MongoDB.Driver

Install the MongoDB.Driver NuGet package from Visual Studio.

Install MongoDB.Driver

Step 2: Configure MongoDB Settings

Add your connection details to appsettings.json.

{ "MongoDbSettings": { "ConnectionString": "mongodb://localhost:27017", "DatabaseName": "MongoWithDotNet", "Collections": { "EmployeeCollection": "Employees" } } }

The important settings are:

  • ConnectionString: the MongoDB server URL
  • DatabaseName: the database to use
  • Collections: the collection names used by the app

Step 3: Register the MongoDB Client

Register the client in Program.cs or Startup.cs.

var connectionString = builder.Configuration.GetValue<string>("MongoDbSettings:ConnectionString"); var settings = MongoClientSettings.FromUrl(new MongoUrl(connectionString)); settings.SslSettings = new SslSettings() { EnabledSslProtocols = SslProtocols.Tls12 }; builder.Services.AddSingleton<IMongoClient>(new MongoClient(settings));

This registers a singleton MongoDB client so the app can use MongoDB through dependency injection.

Understanding MongoDB Database Operations

The article demonstrates these database-level operations:

  • Create collection
  • Drop collection
  • Rename collection
  • List collections
  • Get collection

Database Controller Constructor

private readonly IMongoDatabase _database; public MongoDatabaseController(IMongoClient mongoClient, IConfiguration configuration) { var databaseName = configuration.GetValue<string>("MongoDbSettings:DatabaseName"); _database = mongoClient.GetDatabase(databaseName); }

Creating a Collection

[HttpPost("create-collection/{name}")] public async Task<IActionResult> CreateCollection(string name) { try { await _database.CreateCollectionAsync(name); return Ok($"Collection '{name}' created successfully."); } catch (Exception ex) { return StatusCode(500, $"Failed to create collection '{name}'. Error: {ex.Message}"); } }

MongoDB can create collections automatically, but creating them explicitly is useful when you want to define them ahead of time.

Dropping a Collection

[HttpDelete("drop-collection/{name}")] public async Task<IActionResult> DropCollection(string name) { try { await _database.DropCollectionAsync(name); return Ok($"Collection '{name}' dropped successfully."); } catch (Exception ex) { return StatusCode(500, $"Failed to drop collection '{name}'. Error: {ex.Message}"); } }

Listing Collections

[HttpGet("list-collections")] public async Task<IActionResult> ListCollections() { try { var cursor = await _database.ListCollectionNamesAsync(); var collectionNames = await cursor.ToListAsync(); return Ok(collectionNames); } catch (Exception ex) { return StatusCode(500, $"Failed to retrieve collection names. Error: {ex.Message}"); } }

Renaming a Collection

[HttpPost("rename-collection/{oldName}/{newName}")] public async Task<IActionResult> RenameCollection(string oldName, string newName) { try { await _database.RenameCollectionAsync(oldName, newName); return Ok($"Collection '{oldName}' renamed to '{newName}' successfully."); } catch (Exception ex) { return StatusCode(500, $"Failed to rename collection '{oldName}' to '{newName}'. Error: {ex.Message}"); } }

Getting a Collection

[HttpPost("get-collection/{collectionName}")] public IActionResult GetCollection(string collectionName) { var collection = _database.GetCollection<Employee>(collectionName); return Ok(); }

Understanding MongoDB Collection Operations

The article also covers these collection-level operations:

  • Insert
  • Find
  • Replace
  • Update
  • Delete
  • EstimatedDocumentCount
  • CountDocuments

Employee Model

public class Employee { [BsonId] [BsonRepresentation(BsonType.ObjectId)] public string Id { get; set; } public string Name { get; set; } public int Age { get; set; } public string Designation { get; set; } public decimal Salary { get; set; } }

Collection Controller Constructor

public class MongoCollectionController : ControllerBase { private readonly IMongoCollection<Employee> _employeeCollection; public MongoCollectionController(IMongoClient mongoClient, IConfiguration configuration) { var databaseName = configuration.GetValue<string>("MongoDbSettings:DatabaseName"); var employeeCollectionName = configuration.GetValue<string>("MongoDbSettings:Collections:EmployeeCollection"); var database = mongoClient.GetDatabase(databaseName); _employeeCollection = database.GetCollection<Employee>(employeeCollectionName); } }

Insert a Document

[HttpPost("create")] public async Task<IActionResult> Create() { try { var employee = new Employee { Id = ObjectId.GenerateNewId().ToString(), Name = "John Doe", Age = 30 }; await _employeeCollection.InsertOneAsync(employee); return Ok(); } catch (MongoWriteException ex) { return BadRequest($"Failed to insert document: {ex.Message}"); } }

MongoDB guarantees the uniqueness of the _id field, so duplicate IDs will throw a MongoWriteException.

Insert Many Documents

[HttpPost("create-many")] public async Task<IActionResult> CreateMany() { var employees = new List<Employee> { new Employee { Id = ObjectId.GenerateNewId().ToString(), Name = "Test 1", Age = 25, Designation = "SSE", Salary = 15000 }, new Employee { Id = ObjectId.GenerateNewId().ToString(), Name = "Test 2", Age = 35, Designation = "Team Leader", Salary = 105000 }, new Employee { Id = ObjectId.GenerateNewId().ToString(), Name = "Test 3", Age = 35, Designation = "Test", Salary = 151022 }, new Employee { Id = ObjectId.GenerateNewId().ToString(), Name = "Test 4", Age = 35, Designation = "Demo", Salary = 1500 } }; await _employeeCollection.InsertManyAsync(employees); return Ok(); }

Get All Documents

[HttpGet("all")] public async Task<IActionResult> GetAll() { var employees = await _employeeCollection.Find(Builders<Employee>.Filter.Empty).ToListAsync(); return Ok(employees); }

Get Document by Id

[HttpGet("get-by-id/{id}")] public async Task<IActionResult> GetById([FromRoute] string id) { var employee = await _employeeCollection .Find(Builders<Employee>.Filter.Eq(p => p.Id, id)) .FirstOrDefaultAsync(); return Ok(employee); }

Replace Whole Document

[HttpPut("replace/{id}")] public async Task<IActionResult> Replace([FromRoute] string id) { var filter = Builders<Employee>.Filter.Eq(p => p.Id, id); var employee = new Employee { Id = id, Name = "Updated Name", Age = 40 }; var result = await _employeeCollection.ReplaceOneAsync(filter, employee); return Ok(result); }

Update a Particular Field

[HttpPatch("update-field/{id}")] public async Task<IActionResult> UpdateField([FromRoute] string id) { var filter = Builders<Employee>.Filter.Eq(p => p.Id, id); var update = Builders<Employee>.Update.Set(p => p.Name, "Partially Updated Name"); var result = await _employeeCollection.UpdateOneAsync(filter, update); return Ok(result); }

Delete a Document

[HttpDelete("delete/{id}")] public async Task<IActionResult> Delete([FromRoute] string id) { var filter = Builders<Employee>.Filter.Eq(p => p.Id, id); var result = await _employeeCollection.DeleteOneAsync(filter); // var result = _employeeCollection.DeleteManyAsync(filter); return Ok(result); }

Count Documents

[HttpGet("count")] public async Task<IActionResult> CountDocuments() { var count = await _employeeCollection.CountDocumentsAsync(Builders<Employee>.Filter.Empty); return Ok(count); }

Estimated Document Count

[HttpGet("count/estimated")] public async Task<IActionResult> EstimatedDocumentCount() { var count = await _employeeCollection.EstimatedDocumentCountAsync(); return Ok(count); }

Estimated counts are faster, while exact counts scan the collection.

Conclusion

By implementing MongoDB operations in a .NET application, you get efficient management of data stored in MongoDB databases. These operations leverage MongoDB.Driver to provide practical data manipulation capabilities for real-world applications.

The original article also links to the source code on GitHub.