# How to Integrate .NET Applications with a MongoDB Sharded Cluster

> Integrate .NET applications with MongoDB sharded clusters using standard NuGet packages and a connection string listing mongos router endpoints. Learn how to connect and interact seamlessly.

- Repository: [Jin/mongodb-cluster-docker-compose](https://github.com/minhhungit/mongodb-cluster-docker-compose)
- Tags: how-to-guide
- Published: 2026-03-07

---

**You can integrate .NET applications with a MongoDB sharded cluster by connecting to the mongos routers exposed on ports 27117 and 27118, using the standard MongoDB.Driver NuGet package with a connection string that lists both router endpoints.**

The `minhhungit/mongodb-cluster-docker-compose` repository provides a complete Docker-based sharded cluster deployment that you can use to develop and test .NET applications locally. By leveraging the official MongoDB .NET driver, your applications can automatically discover the cluster topology, route queries to appropriate shards, and handle failover without custom logic.

## Architecture Overview

The repository defines a production-style sharded cluster in **[[`docker-compose.yml`](https://github.com/minhhungit/mongodb-cluster-docker-compose/blob/main/docker-compose.yml)](https://github.com/minhhungit/mongodb-cluster-docker-compose/blob/master/docker-compose.yml)** consisting of three distinct layers:

- **Config Servers** (`configsvr01`, `configsvr02`, `configsvr03`): Store metadata and routing information for the cluster.
- **Shards** (3 replica sets): Each shard is a 3-node replica set (`rs-shard-01`, `rs-shard-02`, `rs-shard-03`) with members named `shard01-a/b/c`, `shard02-a/b/c`, and `shard03-a/b/c`.
- **Routers (mongos)** (`router01`): The query router that exposes ports **27117** and **27118** to the host machine, forwarding operations to the appropriate shards.

The initialization logic in **[[`scripts/entrypoint-route.sh`](https://github.com/minhhungit/mongodb-cluster-docker-compose/blob/main/scripts/entrypoint-route.sh)](https://github.com/minhhungit/mongodb-cluster-docker-compose/blob/master/scripts/entrypoint-route.sh)** waits for all replica sets to elect primaries, starts the `mongos` process, and registers each shard using `sh.addShard()`.

## Connecting .NET Applications to the Sharded Cluster

The MongoDB .NET driver treats a sharded cluster as a single logical database when you connect through the mongos routers. You do not need to specify individual shards or config servers in your connection string.

### Connection String Configuration

Target the exposed router ports with a standard MongoDB URI:

```csharp
var connectionString = "mongodb://127.0.0.1:27117,127.0.0.1:27118";
var client = new MongoClient(connectionString);

```

Listing both ports ensures the driver can fail over if one router becomes unavailable. The driver automatically discovers the full cluster topology from whichever router responds first.

### Database and Collection Access

Once connected, interact with the cluster as you would with a standalone instance:

```csharp
var database = client.GetDatabase("MyDatabase");
var collection = database.GetCollection<MyDocument>("MyCollection");

```

The `mongos` router transparently forwards write operations to the correct shard based on the collection's sharding key, and aggregates results from multiple shards for read operations.

## Read and Write Configuration Best Practices

Sharded clusters require careful tuning of **write concern** and **read preference** to balance performance with consistency guarantees.

### Write Concern for Durability

By default, the driver uses `w:1`, acknowledging writes when the primary shard member confirms the operation. For stronger durability across the replica set backing each shard, specify `w:majority`:

```csharp
var settings = MongoClientSettings.FromConnectionString(connectionString);
settings.WriteConcern = WriteConcern.WMajority;
var client = new MongoClient(settings);

```

### Read Preference for Load Distribution

The sample reader in **[[`client/DemoMongoClusterReader/Program.cs`](https://github.com/minhhungit/mongodb-cluster-docker-compose/blob/main/client/DemoMongoClusterReader/Program.cs)](https://github.com/minhhungit/mongodb-cluster-docker-compose/blob/master/client/DemoMongoClusterReader/Program.cs)** demonstrates using `ReadPreference.SecondaryPreferred` to offload read traffic from primary nodes:

```csharp
var collection = database.GetCollection<MyDocument>("MyCollection",
    new MongoCollectionSettings { ReadPreference = ReadPreference.SecondaryPreferred });

```

This setting routes queries to secondary members of the shard replica sets when available, falling back to primaries if necessary.

### Querying by Sharding Key

For optimal performance, include the **sharding key** in your queries. The sample documents use `oemNumber` and `zipCode` as sharding keys. Queries filtering on these fields are routed directly to the relevant shard rather than broadcast to all shards:

```csharp
var filter = Builders<MyDocument>.Filter.Eq(d => d.OemNumber, "ABCD");
var results = await collection.Find(filter).Limit(50).ToListAsync();

```

## Complete .NET Implementation Examples

The repository includes two full .NET console applications in the **`client/`** directory that demonstrate end-to-end integration.

### Document Model

The shared document model in **[[`client/MongoCluster.Messages/User.cs`](https://github.com/minhhungit/mongodb-cluster-docker-compose/blob/main/client/MongoCluster.Messages/User.cs)](https://github.com/minhhungit/mongodb-cluster-docker-compose/blob/master/client/MongoCluster.Messages/User.cs)** maps C# properties to BSON elements:

```csharp
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;

namespace MongoCluster.Messages
{
    public class MyDocument
    {
        [BsonId] public ObjectId Id { get; set; }
        [BsonElement("name")] public string Name { get; set; }
        [BsonElement("supplierId")] public string SupplierId { get; set; }
        [BsonElement("oemNumber")] public string OemNumber { get; set; }
        [BsonElement("blog")] public string Blog { get; set; }
        [BsonElement("zipCode")] public string ZipCode { get; set; }
        [BsonElement("location")] public string Location { get; set; }
    }
}

```

### Bulk Write Operations

The writer application in **[[`client/DemoMongoClusterWriter/Program.cs`](https://github.com/minhhungit/mongodb-cluster-docker-compose/blob/main/client/DemoMongoClusterWriter/Program.cs)](https://github.com/minhhungit/mongodb-cluster-docker-compose/blob/master/client/DemoMongoClusterWriter/Program.cs)** generates test data and performs unordered bulk inserts for maximum throughput:

```csharp
using MongoCluster.Messages;
using MongoDB.Bson;
using MongoDB.Driver;
using System;
using System.Collections.Generic;
using System.Diagnostics;

var dbName = "MyDatabase";
var client = new MongoClient("mongodb://127.0.0.1:27117,127.0.0.1:27118");
var database = client.GetDatabase(dbName);
var collection = database.GetCollection<MyDocument>("MyCollection");

// Build a batch of 10,000 documents
var batch = new List<MyDocument>();
for (int i = 0; i < 10_000; i++)
{
    batch.Add(new MyDocument
    {
        Id = ObjectId.GenerateNewId(),
        SupplierId = Guid.NewGuid().ToString(),
        OemNumber = RandomString(4),
        ZipCode = new Random().Next(1, 1000).ToString("D4"),
        Name = $"Demo {i}"
    });
}

// Fire-and-forget bulk insert (unordered for speed)
collection.InsertManyAsync(batch, new InsertManyOptions { IsOrdered = false })
          .GetAwaiter().GetResult();

```

### Secondary-Preferred Reads

The reader application in **[[`client/DemoMongoClusterReader/Program.cs`](https://github.com/minhhungit/mongodb-cluster-docker-compose/blob/main/client/DemoMongoClusterReader/Program.cs)](https://github.com/minhhungit/mongodb-cluster-docker-compose/blob/master/client/DemoMongoClusterReader/Program.cs)** demonstrates querying with specific read preferences and filters:

```csharp
using MongoCluster.Messages;
using MongoDB.Bson;
using MongoDB.Driver;
using System;
using System.Threading.Tasks;

var client = new MongoClient("mongodb://127.0.0.1:27117,127.0.0.1:27118");
var database = client.GetDatabase("MyDatabase");

// Read from a secondary when possible
var collection = database.GetCollection<MyDocument>("MyCollection",
    new MongoCollectionSettings { ReadPreference = ReadPreference.SecondaryPreferred });

var filter = Builders<MyDocument>.Filter.Eq(d => d.OemNumber, "ABCD");
var results = await collection.Find(filter).Limit(50).ToListAsync();

Console.WriteLine($"Found {results.Count} documents");

```

## Running the Complete Integration

Follow these steps to start the cluster and execute the .NET samples.

### 1. Start the MongoDB Cluster

Execute Docker Compose to initialize the config servers, shard replica sets, and mongos routers:

```bash
docker-compose up -d

```

The **[[`scripts/entrypoint-route.sh`](https://github.com/minhhungit/mongodb-cluster-docker-compose/blob/main/scripts/entrypoint-route.sh)](https://github.com/minhhungit/mongodb-cluster-docker-compose/blob/master/scripts/entrypoint-route.sh)** script automatically waits for all replica sets to elect primaries, starts the `mongos` process, and registers each shard using `sh.addShard()`.

### 2. Execute the Writer Application

Run the bulk insert sample to populate the cluster with test data:

```bash
dotnet run --project client/DemoMongoClusterWriter/DemoMongoClusterWriter.csproj

```

### 3. Execute the Reader Application

Query the data using secondary-preferred read preferences:

```bash
dotnet run --project client/DemoMongoClusterReader/DemoMongoClusterReader.csproj

```

The .NET driver automatically discovers the sharding topology via the mongos routers and distributes operations across the appropriate replica sets.

## Summary

- **Connection Method**: Point your `MongoClient` to the mongos routers exposed on ports **27117** and **27118** using a standard MongoDB connection string.
- **Automatic Topology Discovery**: The .NET driver retrieves cluster metadata from the mongos and routes queries to the correct shards without manual configuration.
- **Write Optimization**: Use `InsertManyAsync` with `IsOrdered = false` for high-throughput bulk writes across the sharded cluster.
- **Read Distribution**: Configure `ReadPreference.SecondaryPreferred` in `MongoCollectionSettings` to offload read traffic from primary nodes.
- **Query Performance**: Include the sharding key (e.g., `oemNumber` or `zipCode`) in your filters to enable targeted shard routing instead of cluster-wide broadcasts.

## Frequently Asked Questions

### What is the correct connection string for connecting .NET applications to this MongoDB sharded cluster?

Use a connection string that lists both mongos router endpoints exposed by the Docker Compose setup: `mongodb://127.0.0.1:27117,127.0.0.1:27118`. The .NET driver will automatically discover the full cluster topology from whichever router responds first, and will handle failover if one router becomes unavailable.

### How does the .NET driver handle routing queries to specific shards?

The MongoDB .NET driver communicates with the **mongos** routers (configured in `router01`), which maintain metadata about which shard holds each document based on the sharding key. When you execute a query that includes the sharding key (such as `oemNumber` or `zipCode` in the sample documents), the mongos routes the operation directly to the relevant shard. For queries without the sharding key, mongos broadcasts to all shards and aggregates results.

### Can I configure read preferences to reduce load on primary shard members?

Yes. You can specify `ReadPreference.SecondaryPreferred` when retrieving a collection, as demonstrated in **[[`client/DemoMongoClusterReader/Program.cs`](https://github.com/minhhungit/mongodb-cluster-docker-compose/blob/main/client/DemoMongoClusterReader/Program.cs)](https://github.com/minhhungit/mongodb-cluster-docker-compose/blob/master/client/DemoMongoClusterReader/Program.cs)**. This setting directs the driver to read from secondary members of the shard replica sets when available, falling back to primaries only when necessary. This significantly reduces read load on primary nodes and improves overall cluster throughput.

### What write concern should I use for a sharded cluster to ensure data durability?

While the default `w:1` write concern acknowledges writes when the primary shard member confirms the operation, you should use **`WriteConcern.WMajority`** for production workloads. This ensures the write is acknowledged by a majority of nodes in the replica set backing the shard, guaranteeing durability even if the primary fails immediately after the write. You can configure this via `MongoClientSettings` before instantiating the `MongoClient`.