HomeNikola Knezevic

In this article

Banner

MongoDB with EF Core

15 Oct 2026
6 min

Special Thanks to Our Sponsors:

Sponsor Logo

EF Core is too slow? Discover how you can easily insert 14x faster (reducing saving time by 94%).

Boost your performance with our method within EF Core: Bulk Insert, update, delete and merge.

Thousands of satisfied customers have trusted our library since 2014.

👉 Learn more

Sponsor Newsletter

When building .NET applications, many of us reach for Entity Framework Core by default.

It gives us a familiar programming model with DbContext, change tracking and LINQ. For relational databases that works great.

But sometimes a document database fits the problem better. Flexible schemas, nested documents and horizontal scaling are common reasons teams look at MongoDB.

The trade-off used to be painful. You either kept EF Core and stayed relational, or switched to the MongoDB driver and left the EF Core patterns behind.

That's where the official MongoDB EF Core Provider comes in. It lets you use EF Core against MongoDB with the same DbContext and LINQ style you already know.

MongoDB EF Core Provider

The MongoDB Entity Framework Core Provider is the official package that bridges EF Core and MongoDB.

Instead of writing driver-specific queries everywhere, you work with entities, DbSet<T> and SaveChangesAsync. The provider translates your LINQ into MongoDB operations.

This is especially useful when:

  • You already know EF Core - Keep the same mental model while adopting MongoDB
  • You want change tracking - Update entities and persist with SaveChanges
  • You care about consistency in the codebase - One data-access style across projects

Under the hood, DbContext still acts as your unit of work. If you want a deeper look at that idea, check out my blog post on the Unit of Work Pattern in .NET.

Getting Started

To get started, install the MongoDB.EntityFrameworkCore package. Pick the version that matches your EF Core major version.

shell
dotnet add package MongoDB.EntityFrameworkCore

You'll also need a MongoDB instance. In my sample I run MongoDB with Docker Compose, including mongo-express for a simple UI.

yaml
services:
  mongodb:
    image: mongo:latest
    container_name: mongodb
    environment:
      - MONGO_INITDB_ROOT_USERNAME=admin
      - MONGO_INITDB_ROOT_PASSWORD=admin
    ports:
      - "27017:27017"
    restart: always

From provider 8.1, SaveChanges can open a transaction when more than one root entity changes. A standalone MongoDB server rejects that. Use a replica set, even a single node or set AutoTransactionBehavior to Never.

Then add the connection string to configuration:

json
{
  "ConnectionStrings": {
    "Database": "mongodb://admin:admin@localhost:27017"
  }
}

Entity and DbContext

From here, the model looks like any other EF Core project. Here's a simple Product entity:

csharp
public sealed class Product
{
    public Guid Id { get; set; }

    public DateTime CreatedAt { get; set; }

    public DateTime? ModifiedAt { get; set; }

    public string Name { get; set; }

    public string Description { get; set; }

    public decimal Price { get; set; }

    public Product(
        Guid id,
        DateTime createdAt,
        string name,
        string description,
        decimal price)
    {
        Id = id;
        CreatedAt = createdAt;
        Name = name;
        Description = description;
        Price = price;
        ModifiedAt = null;
    }

    public void Update(string name, string description, decimal price)
    {
        Name = name;
        Description = description;
        Price = price;
    }
}

And an ApplicationDbContext with a Products set:

csharp
public class ApplicationDbContext(DbContextOptions options)
    : DbContext(options), IApplicationDbContext
{
    protected override void OnModelCreating(ModelBuilder modelBuilder) =>
        modelBuilder.ApplyConfigurationsFromAssembly(Assembly.GetExecutingAssembly());

    public DbSet<Product> Products { get; set; }
}

By default, the provider maps the DbSet name to a MongoDB collection. You can also map explicitly with ToCollection in OnModelCreating if you want a different collection name.

Configuring UseMongoDB

The important difference from SQL Server or PostgreSQL is how you register the provider.

Instead of UseNpgsql or UseSqlServer, you call UseMongoDB with a connection string and a database name:

csharp
public static IServiceCollection AddDatabase(
    this IServiceCollection services,
    IConfiguration configuration)
{
    services.AddDbContext<ApplicationDbContext>(options =>
        options.UseMongoDB(
            configuration.GetConnectionString("Database")!,
            "Products"));

    services.AddScoped<IApplicationDbContext>(
        sp => sp.GetRequiredService<ApplicationDbContext>());

    return services;
}

The second argument is the MongoDB database name, not a schema or table. In this example, documents live in the Products database.

After that, you inject ApplicationDbContext or an abstraction like IApplicationDbContext the same way you would in any ASP.NET Core app.

CRUD with LINQ

Once the context is registered, CRUD looks familiar. Creating a product is just Add plus SaveChangesAsync:

csharp
public async Task<Result<Guid>> Handle(
    Command request,
    CancellationToken cancellationToken)
{
    var product = new Product(
        Guid.NewGuid(),
        DateTime.UtcNow,
        request.Name,
        request.Description,
        request.Price);

    dbContext.Products.Add(product);

    await dbContext.SaveChangesAsync(cancellationToken);

    return Result.Success(product.Id);
}

Reading is plain LINQ. Projection works the same as with relational providers:

csharp
public async Task<IEnumerable<ProductResponse?>> Handle(
    Query request,
    CancellationToken cancellationToken) =>
    await dbContext.Products
        .Select(p => new ProductResponse(
            p.Id,
            p.Name,
            p.Description,
            p.Price))
        .ToListAsync(cancellationToken);

Updates follow the usual change-tracking flow. Load the entity, mutate it, then save:

csharp
var product = await dbContext.Products
    .FirstOrDefaultAsync(x => x.Id == request.Id, cancellationToken);

if (product is null)
{
    return Result.NotFound();
}

product.Update(request.Name, request.Description, request.Price);

await dbContext.SaveChangesAsync(cancellationToken);

And deletes use Remove:

csharp
dbContext.Products.Remove(product);

await dbContext.SaveChangesAsync(cancellationToken);

In short, if you already write EF Core code, MongoDB CRUD will feel natural. The provider handles translating those operations into MongoDB writes and queries.

Limitations to Keep in Mind

MongoDB is not a relational database, so not every EF Core feature maps cleanly.

A few important caveats:

  • No migrations - Migrations are built for relational schemas. MongoDB does not use them
  • No foreign keys - Document databases do not model relationships the SQL way
  • No joins or Includes - Prefer embedded documents instead of normalized cross-collection designs
  • Advanced queries - Some LINQ shapes still need the native MongoDB .NET driver

You can find the full list in the official limitations docs.

NOTE: The provider is a great fit when your domain maps well to documents. If you rely heavily on relational modeling, foreign keys and multi-table joins, a SQL provider is still the better choice.

Conclusion

MongoDB with EF Core gives you a familiar API without forcing you into the native driver for every read and write.

You keep DbContext, LINQ and change tracking, while MongoDB stores your data as documents.

Install MongoDB.EntityFrameworkCore, call UseMongoDB, define your entities and you're ready to build.

Just remember the limitations. Design around documents and reach for the MongoDB driver when a query goes beyond what the provider supports.

If you want to check out examples I created, you can find the source code here:

Source Code

I hope you enjoyed it, subscribe and get a notification when a new blog is up!

Related posts
Getting Started with MongoDB in ASP.NET Core
Getting Started with MongoDB in ASP.NET Core

Wire up MongoDB.Driver in ASP.NET Core with options binding, a singleton IMongoClient, BSON document mapping and full CRUD for a Product collection.

Unit of Work Pattern in .NET
Unit of Work Pattern in .NET

Unit of Work is a transaction boundary for related changes, not a DbContext wrapper. With EF Core you already have it. With Dapper, you coordinate the connection and transaction yourself.

Generic Repositories in .NET
Generic Repositories in .NET

Generic repositories reuse common CRUD, but pure ones often become an anti-pattern. A hybrid base repository plus specific interfaces keeps reuse without losing entity-focused queries.

Subscribe

Stay tuned for valuable insights every Thursday morning.