ZetCode

C# MongoDB

last modified October 16, 2026

In this article we show how to work with the MongoDB database in C#.

MongoDB

MongoDB is a NoSQL cross-platform document-oriented database. It is one of the most popular databases available. MongoDB is developed by MongoDB Inc.

A record in MongoDB is a document, which is a data structure composed of field and value pairs. MongoDB documents are similar to JSON objects. The values of fields may include other documents, arrays, and arrays of documents. MongoDB stores documents in collections. Collections are analogous to tables in relational databases and documents to rows.

MongoDB represents JSON documents in a binary-encoded format called BSON behind the scenes. BSON extends the JSON model to provide additional data types, such as dates or 64-bit integers, and to be efficient for encoding and decoding. The .NET driver uses the BsonDocument class to represent BSON documents; it can also map documents to our own C# classes.

MongoDB.Driver

MongoDB.Driver is the official .NET driver for MongoDB.

$ dotnet add package MongoDB.Driver

We add the package to the project. The examples were tested with MongoDB.Driver 3.12 and MongoDB 8.

For testing, we can run MongoDB in a Docker container:

$ docker run -d --name mongo -p 127.0.0.1:27017:27017 mongo:8

MongoDB create database

The mongosh tool is an interactive JavaScript shell for MongoDB. It provides an interface for administrators and a way for developers to test queries and operations directly with the database. It replaced the older mongo shell.

$ docker exec -it mongo mongosh testdb
testdb> db.cars.insertMany([
  { name: "Audi", price: 52642 },
  { name: "Mercedes", price: 57127 },
  { name: "Skoda", price: 9000 },
  { name: "Volvo", price: 29000 },
  { name: "Bentley", price: 350000 },
  { name: "Citroen", price: 21000 },
  { name: "Hummer", price: 41400 },
  { name: "Volkswagen", price: 21600 }
])

A database and a collection are created automatically when we first store data in them. We insert eight documents into the cars collection of the testdb database. We will work with this data in the article.

C# MongoDB list databases

The first example connects to the MongoDB server and retrieves its databases.

Program.cs
using MongoDB.Driver;

var client = new MongoClient("mongodb://127.0.0.1:27017");

var names = client.ListDatabaseNames().ToList();

Console.WriteLine("The databases are:");

foreach (var name in names)
{
    Console.WriteLine(name);
}

The example connects to the MongoDB server and retrieves the names of all its databases.

var client = new MongoClient("mongodb://127.0.0.1:27017");

The MongoClient class is used to connect to the MongoDB server. 27017 is the default port on which the MongoDB server listens. The client is thread-safe and should be reused in an application.

var names = client.ListDatabaseNames().ToList();

We get the database names with the ListDatabaseNames method. The ListDatabases method returns more details, such as the size of each database.

$ dotnet run
The databases are:
admin
config
local
testdb

C# MongoDB RunCommand

The RunCommand method runs a database command.

Program.cs
using MongoDB.Bson;
using MongoDB.Driver;

var client = new MongoClient("mongodb://127.0.0.1:27017");
IMongoDatabase db = client.GetDatabase("testdb");

var command = new BsonDocument { { "dbstats", 1 } };
var result = db.RunCommand<BsonDocument>(command);

Console.WriteLine($"Database: {result["db"]}");
Console.WriteLine($"Collections: {result["collections"]}");
Console.WriteLine($"Documents: {result["objects"]}");
Console.WriteLine($"Indexes: {result["indexes"]}");

The example connects to the testdb database and gets its statistics.

IMongoDatabase db = client.GetDatabase("testdb");

We get the database with the GetDatabase method.

var command = new BsonDocument { { "dbstats", 1 } };
var result = db.RunCommand<BsonDocument>(command);

With the RunCommand method, we execute the dbstats command. The result is a BsonDocument. We access its fields with the indexer and print some of them.

$ dotnet run
Database: testdb
Collections: 1
Documents: 8
Indexes: 1

C# MongoDB mapping to classes

The driver can map documents to our own classes. In the following examples, we use the Car class.

Car.cs
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;

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

    [BsonElement("name")]
    public string Name { get; set; } = "";

    [BsonElement("price")]
    public int Price { get; set; }

    public override string ToString() => $"{Name} {Price}";
}

The [BsonId] attribute marks the property that holds the unique _id of a document; MongoDB generates an ObjectId for every new document. The [BsonElement] attribute maps a property to a document field with a different name.

C# MongoDB find document

We query for a document with a specific filter. The filter is given to the Find method.

Program.cs
using MongoDB.Driver;

var client = new MongoClient("mongodb://127.0.0.1:27017");
var db = client.GetDatabase("testdb");

var cars = db.GetCollection<Car>("cars");

var filter = Builders<Car>.Filter.Eq(c => c.Price, 29000);
Car? car = cars.Find(filter).FirstOrDefault();

Console.WriteLine(car);

The example finds a car whose price is 29000.

var cars = db.GetCollection<Car>("cars");

We get the cars collection with the GetCollection method. The type parameter tells the driver to map the documents to Car objects.

var filter = Builders<Car>.Filter.Eq(c => c.Price, 29000);

A filter is created with the Builders class; we look for a car with a price equal to 29000. Thanks to the lambda expression, the filter is type-safe; the driver uses the field name from the [BsonElement] attribute.

Car? car = cars.Find(filter).FirstOrDefault();

We pass the filter to the Find method and retrieve the first matching document with FirstOrDefault.

$ dotnet run
Volvo 29000

C# MongoDB find all documents

An empty filter matches all documents.

Program.cs
using MongoDB.Driver;

var client = new MongoClient("mongodb://127.0.0.1:27017");
var cars = client.GetDatabase("testdb").GetCollection<Car>("cars");

List<Car> all = await cars.Find(Builders<Car>.Filter.Empty).ToListAsync();

foreach (var car in all)
{
    Console.WriteLine(car);
}

The example retrieves all documents from the cars collection. The driver has asynchronous versions of its methods; here we use ToListAsync.

$ dotnet run
Audi 52642
Mercedes 57127
Skoda 9000
Volvo 29000
Bentley 350000
Citroen 21000
Hummer 41400
Volkswagen 21600

C# MongoDB query

MongoDB supports several query operators, such as Gt, Lt, or Gte. The filters can be combined with the & and | operators. The results can be sorted.

Program.cs
using MongoDB.Driver;

var client = new MongoClient("mongodb://127.0.0.1:27017");
var cars = client.GetDatabase("testdb").GetCollection<Car>("cars");

var builder = Builders<Car>.Filter;
var filter = builder.Gt(c => c.Price, 30000) & builder.Lt(c => c.Price, 55000);

var res = cars.Find(filter).SortBy(c => c.Price).ToList();

foreach (var car in res)
{
    Console.WriteLine(car);
}

The example prints all cars whose prices are between 30000 and 55000, sorted by price.

var filter = builder.Gt(c => c.Price, 30000) & builder.Lt(c => c.Price, 55000);

We build a filter with two operators: Gt and Lt.

$ dotnet run
Hummer 41400
Audi 52642

We have found two documents that match the criteria.

C# MongoDB LINQ

The driver also supports LINQ queries. The AsQueryable method returns an IQueryable; the LINQ query is translated to a MongoDB query and executed on the server.

Program.cs
using MongoDB.Driver;

var client = new MongoClient("mongodb://127.0.0.1:27017");
var cars = client.GetDatabase("testdb").GetCollection<Car>("cars");

var cheap = cars.AsQueryable()
    .Where(c => c.Price < 25000)
    .OrderBy(c => c.Name)
    .Select(c => c.Name)
    .ToList();

Console.WriteLine(string.Join(", ", cheap));

var avg = cars.AsQueryable().Average(c => c.Price);
Console.WriteLine($"Average price: {avg:F2}");

We get the names of the cheap cars and the average price of all cars.

$ dotnet run
Citroen, Skoda, Volkswagen
Average price: 72721.12

C# MongoDB skip and limit

The Limit method specifies the number of documents to be returned and the Skip method skips the specified number of documents. Together, they are used for paging.

Program.cs
using MongoDB.Driver;

var client = new MongoClient("mongodb://127.0.0.1:27017");
var cars = client.GetDatabase("testdb").GetCollection<Car>("cars");

var page = cars.Find(Builders<Car>.Filter.Empty)
    .SortBy(c => c.Name)
    .Skip(3)
    .Limit(3)
    .ToList();

foreach (var car in page)
{
    Console.WriteLine(car);
}

The example sorts the cars by name, skips the first three documents, and limits the output to three documents. Without sorting, the order of the documents is not guaranteed.

$ dotnet run
Hummer 41400
Mercedes 57127
Skoda 9000

C# MongoDB insert document

A new document is inserted into a collection with the InsertOne method; the InsertMany method inserts several documents.

Program.cs
using MongoDB.Driver;

var client = new MongoClient("mongodb://127.0.0.1:27017");
var cars = client.GetDatabase("testdb").GetCollection<Car>("cars");

var car = new Car { Name = "BMW", Price = 34621 };
await cars.InsertOneAsync(car);

Console.WriteLine($"Inserted {car.Name} with id {car.Id.GetType().Name}");
Console.WriteLine(await cars.CountDocumentsAsync(Builders<Car>.Filter.Empty));

The example inserts a new car into the cars collection.

await cars.InsertOneAsync(car);

After the insertion, the driver sets the Id property of the object to the generated ObjectId.

Console.WriteLine(await cars.CountDocumentsAsync(Builders<Car>.Filter.Empty));

The collection now contains nine documents.

$ dotnet run
Inserted BMW with id ObjectId
9

C# MongoDB update document

The UpdateOne method updates the first document that matches a filter. The changes are described with the Builders.Update definitions.

Program.cs
using MongoDB.Driver;

var client = new MongoClient("mongodb://127.0.0.1:27017");
var cars = client.GetDatabase("testdb").GetCollection<Car>("cars");

var filter = Builders<Car>.Filter.Eq(c => c.Name, "Audi");
var update = Builders<Car>.Update.Set(c => c.Price, 52000);

UpdateResult res = await cars.UpdateOneAsync(filter, update);
Console.WriteLine($"Matched: {res.MatchedCount}, modified: {res.ModifiedCount}");

var discount = Builders<Car>.Update.Mul(c => c.Price, 0.9);
var cheap = Builders<Car>.Filter.Lt(c => c.Price, 25000);

UpdateResult res2 = await cars.UpdateManyAsync(cheap, discount);
Console.WriteLine($"Discounted cars: {res2.ModifiedCount}");

foreach (var car in await cars.Find(cheap).SortBy(c => c.Price).ToListAsync())
{
    Console.WriteLine(car);
}

We change the price of the Audi and give a ten percent discount on all cars cheaper than 25000.

var discount = Builders<Car>.Update.Mul(c => c.Price, 0.9);

The Mul update multiplies the value of a field. The update is performed on the server; the documents are not transferred to the client. Since we multiply by a floating point number, MongoDB stores the results as doubles. Reading them into the int property works here, because the results are whole numbers; otherwise, the driver would throw an exception. For prices, the decimal type would be a better choice in a real application.

$ dotnet run
Matched: 1, modified: 1
Discounted cars: 3
Skoda 8100
Citroen 18900
Volkswagen 19440

C# MongoDB delete document

The DeleteOne method deletes the first document that matches the filter; the DeleteMany method deletes all matching documents.

Program.cs
using MongoDB.Driver;

var client = new MongoClient("mongodb://127.0.0.1:27017");
var cars = client.GetDatabase("testdb").GetCollection<Car>("cars");

var filter = Builders<Car>.Filter.Eq(c => c.Name, "BMW");
DeleteResult res = await cars.DeleteOneAsync(filter);

Console.WriteLine($"Deleted: {res.DeletedCount}");
Console.WriteLine(await cars.CountDocumentsAsync(Builders<Car>.Filter.Empty));

The example deletes the BMW car, which we have inserted earlier.

$ dotnet run
Deleted: 1
8

Source

MongoDB C# Driver documentation

In this article we have worked with MongoDB in C#.

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all C# tutorials.