| name | abp-mongodb |
| description | ABP Framework v10.x (10.4/10.5) MongoDB: AbpMongoDbContext, collection mapping, index, transaction, replica set, repository. Use when working with MongoDB, document databases, or MongoDB repositories in ABP. |
ABP Framework — MongoDB
ABP Framework v10.x (10.4/10.5) MongoDB integration guide. MongoDbContext, collection mapping, repository, indexes, transactions.
Trigger
- "ABP MongoDB"
- "ABP MongoDbContext"
- "ABP Mongo repository"
- "ABP Mongo collection"
- "ABP Mongo index"
- "ABP Mongo transaction"
Installation
abp add-package Volo.Abp.MongoDB
[DependsOn(typeof(AbpMongoDbModule))]
public class MyModule : AbpModule { }
MongoDbContext
public class MyDbContext : AbpMongoDbContext
{
public IMongoCollection<Question> Questions => Collection<Question>();
public IMongoCollection<Category> Categories => Collection<Category>();
protected override void CreateModel(IMongoModelBuilder modelBuilder)
{
base.CreateModel(modelBuilder);
}
}
Collection Mapping
protected override void CreateModel(IMongoModelBuilder modelBuilder)
{
base.CreateModel(modelBuilder);
modelBuilder.Entity<Question>(b =>
{
b.CollectionName = "MyQuestions";
b.BsonMap.UnmapProperty(x => x.MyProperty);
});
}
Or via attribute:
[MongoCollection("MyQuestions")]
public IMongoCollection<Question> Questions => Collection<Question>();
Index Configuration
protected override void CreateModel(IMongoModelBuilder modelBuilder)
{
base.CreateModel(modelBuilder);
modelBuilder.Entity<Question>(b =>
{
b.CreateCollectionOptions.Collation = new Collation(locale: "en_US", strength: CollationStrength.Secondary);
b.ConfigureIndexes(indexes =>
{
indexes.CreateOne(
new CreateIndexModel<BsonDocument>(
Builders<BsonDocument>.IndexKeys.Ascending("MyProperty"),
new CreateIndexOptions { Unique = true }
)
);
});
});
}
DbContext Registration
context.Services.AddMongoDbContext<MyDbContext>(options =>
{
options.AddDefaultRepositories();
});
Using the Default Repository
public class BookManager : DomainService
{
private readonly IRepository<Book, Guid> _bookRepository;
public BookManager(IRepository<Book, Guid> bookRepository) => _bookRepository = bookRepository;
public async Task<Book> CreateBookAsync(string name, BookType type)
{
var book = new Book(GuidGenerator.Create(), name, type);
await _bookRepository.InsertAsync(book);
return book;
}
}
Custom Repository
public interface IBookRepository : IRepository<Book, Guid>
{
Task DeleteBooksByTypeAsync(BookType type, CancellationToken cancellationToken = default);
}
public class BookRepository : MongoDbRepository<MyMongoDbContext, Book, Guid>, IBookRepository
{
public BookRepository(IMongoDbContextProvider<MyMongoDbContext> dbContextProvider)
: base(dbContextProvider) { }
public async Task DeleteBooksByTypeAsync(BookType type, CancellationToken cancellationToken = default)
{
var collection = await GetCollectionAsync(cancellationToken);
await collection.DeleteManyAsync(
Builders<Book>.Filter.Eq(b => b.Type, type),
cancellationToken
);
}
}
Default Repository Override
context.Services.AddMongoDbContext<MyMongoDbContext>(options =>
{
options.AddDefaultRepositories();
options.AddRepository<Book, BookRepository>();
});
MongoDB API Access
public class BookService
{
private readonly IRepository<Book, Guid> _bookRepository;
public BookService(IRepository<Book, Guid> bookRepository) => _bookRepository = bookRepository;
public async Task FooAsync()
{
IMongoDatabase database = await _bookRepository.GetDatabaseAsync();
IMongoCollection<Book> books = await _bookRepository.GetCollectionAsync();
IAggregateFluent<Book> aggregate = await _bookRepository.GetAggregateAsync();
}
}
A reference to the Volo.Abp.MongoDB package is required.
Transactions
MongoDB 4.0+ supports multi-document transactions. In the startup templates, transactions are disabled by default.
Enabling Transactions
Docker Replica Set (for Transactions)
version: "3.8"
services:
mongo:
image: mongo:8.0
command: ["--replSet", "rs0", "--bind_ip_all", "--port", "27017"]
ports:
- 27017:27017
healthcheck:
test: echo "try { rs.status() } catch (err) { rs.initiate({_id:'rs0',members:[{_id:0,host:'127.0.0.1:27017'}]}) }" | mongosh --port 27017 --quiet
interval: 5s
timeout: 30s
start_period: 0s
start_interval: 1s
retries: 30
Connection string: mongodb://localhost:27017/YourProjectName?replicaSet=rs0
Connection String Selection
[ConnectionStringName("MySecondConnString")]
public class MyDbContext : AbpMongoDbContext { }
Multi-Tenancy
[IgnoreMultiTenancy]
public class TenantManagementMongoDbContext : AbpMongoDbContext { }
Default Repository Base Class
public class MyRepositoryBase<TEntity> : MongoDbRepository<MyMongoDbContext, TEntity>
where TEntity : class, IEntity
{
public MyRepositoryBase(IMongoDbContextProvider<MyMongoDbContext> dbContextProvider)
: base(dbContextProvider) { }
}
context.Services.AddMongoDbContext<MyMongoDbContext>(options =>
{
options.SetDefaultRepositoryClasses(typeof(MyRepositoryBase<,>), typeof(MyRepositoryBase<>));
});
ReplaceDbContext Pattern
public interface IBookStoreMongoDbContext : IAbpMongoDbContext
{
IMongoCollection<Book> Books { get; }
}
[ReplaceDbContext(typeof(IBookStoreMongoDbContext))]
public class OtherMongoDbContext : AbpMongoDbContext, IBookStoreMongoDbContext { }
context.Services.AddMongoDbContext<OtherMongoDbContext>(options =>
{
options.ReplaceDbContext<IBookStoreMongoDbContext>();
});
Bulk Operations Customization
public class MyCustomMongoDbBulkOperationProvider : IMongoDbBulkOperationProvider, ITransientDependency
{
public async Task InsertManyAsync<TEntity>(
IMongoDbRepository<TEntity> repository,
IEnumerable<TEntity> entities,
IClientSessionHandle sessionHandle,
bool autoSave,
CancellationToken cancellationToken)
{
}
public async Task UpdateManyAsync<TEntity>(...) { }
public async Task DeleteManyAsync<TEntity>(...) { }
}
EF Core vs MongoDB Comparison
| Feature | EF Core | MongoDB |
|---|
| DbContext | AbpDbContext<T> | AbpMongoDbContext |
| Collection | DbSet<T> | IMongoCollection<T> |
| Mapping | Fluent API / Data Annotations | IMongoModelBuilder |
| Repository Base | EfCoreRepository | MongoDbRepository |
| Query | IQueryable (LINQ) | MongoDB Filter/Aggregate |
| Transaction | Enabled by default | Disabled by default |
| Change Tracking | Yes | No |
Best Practices
- Use
AbpMongoDbContext — Instead of directly using IMongoDatabase
- Define collection names via attribute —
[MongoCollection("name")]
- Define indexes in
CreateModel — A migration-like approach
- Set up a replica set if you need transactions — A single node does not support transactions
- Define custom repositories in the MongoDB layer — Only the interface in the domain layer
- Use
IAsyncQueryableExecuter — Keep the domain layer isolated from MongoDB
- Extra Properties are natively supported in MongoDB — Stored as a separate element instead of a JSON field
What's New in v10.5
- MongoDB.Driver upgraded to 3.9.0 (v10.5+). If your solution pins MongoDB.Driver directly, align it with ABP's version and re-run integration tests that use the driver directly.
Related