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.
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.
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:
{
"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:
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:
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:
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:
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:
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:
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:
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 CodeI hope you enjoyed it, subscribe and get a notification when a new blog is up!



