.agents/skills/abp-mongodb/SKILL.md
ABP MongoDB patterns - AbpMongoDbContext, IMongoCollection, MongoDbRepository, no migrations, embedded documents vs references, manual UpdateAsync required. Use when working in MongoDB projects or implementing MongoDB repositories in ABP.
npx skillsauth add afonsoft/VideoChat abp-mongodbInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Docs: https://abp.io/docs/latest/framework/data/mongodb
[ConnectionStringName("Default")]
public class MyProjectMongoDbContext : AbpMongoDbContext
{
public IMongoCollection<Book> Books => Collection<Book>();
public IMongoCollection<Author> Authors => Collection<Author>();
protected override void CreateModel(IMongoModelBuilder modelBuilder)
{
base.CreateModel(modelBuilder);
modelBuilder.ConfigureMyProject();
}
}
public static class MyProjectMongoDbContextExtensions
{
public static void ConfigureMyProject(this IMongoModelBuilder builder)
{
Check.NotNull(builder, nameof(builder));
builder.Entity<Book>(b =>
{
b.CollectionName = MyProjectConsts.DbTablePrefix + "Books";
});
builder.Entity<Author>(b =>
{
b.CollectionName = MyProjectConsts.DbTablePrefix + "Authors";
});
}
}
public class BookRepository : MongoDbRepository<MyProjectMongoDbContext, Book, Guid>, IBookRepository
{
public BookRepository(IMongoDbContextProvider<MyProjectMongoDbContext> dbContextProvider)
: base(dbContextProvider)
{
}
public async Task<Book> FindByNameAsync(
string name,
bool includeDetails = true,
CancellationToken cancellationToken = default)
{
return await (await GetQueryableAsync())
.FirstOrDefaultAsync(
b => b.Name == name,
GetCancellationToken(cancellationToken));
}
public async Task<List<Book>> GetListByAuthorAsync(
Guid authorId,
bool includeDetails = false,
CancellationToken cancellationToken = default)
{
return await (await GetQueryableAsync())
.Where(b => b.AuthorId == authorId)
.ToListAsync(GetCancellationToken(cancellationToken));
}
}
[DependsOn(typeof(AbpMongoDbModule))]
public class MyProjectMongoDbModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddMongoDbContext<MyProjectMongoDbContext>(options =>
{
// Add default repositories for aggregate roots only (DDD best practice)
options.AddDefaultRepositories();
// ⚠️ Avoid includeAllEntities: true - breaks DDD data consistency
});
}
}
In appsettings.json:
{
"ConnectionStrings": {
"Default": "mongodb://localhost:27017/MyProjectDb"
}
}
MongoDB is schema-less; no migrations needed. Changes to entity structure are handled automatically.
Often ignored in MongoDB because documents typically embed related data:
public async Task<List<Book>> GetListAsync(
bool includeDetails = false, // Usually ignored
CancellationToken cancellationToken = default)
{
// MongoDB documents already include nested data
return await (await GetQueryableAsync())
.ToListAsync(GetCancellationToken(cancellationToken));
}
// Embedded (stored in same document)
public class Order : AggregateRoot<Guid>
{
public List<OrderLine> Lines { get; set; } // Embedded
}
// Reference (separate collection, store ID only)
public class Order : AggregateRoot<Guid>
{
public Guid CustomerId { get; set; } // Reference by ID
}
MongoDB doesn't track entity changes automatically:
public async Task UpdateBookAsync(Guid id, string newName)
{
var book = await _bookRepository.GetAsync(id);
book.SetName(newName);
// Must explicitly update
await _bookRepository.UpdateAsync(book);
}
public async Task CustomOperationAsync()
{
var collection = await GetCollectionAsync();
// Use MongoDB driver directly
var filter = Builders<Book>.Filter.Eq(b => b.AuthorId, authorId);
var update = Builders<Book>.Update.Set(b => b.IsPublished, true);
await collection.UpdateManyAsync(filter, update);
}
Configure indexes in repository or via MongoDB driver:
public class BookRepository : MongoDbRepository<MyProjectMongoDbContext, Book, Guid>, IBookRepository
{
public override async Task<IQueryable<Book>> GetQueryableAsync()
{
var collection = await GetCollectionAsync();
// Ensure index exists
var indexKeys = Builders<Book>.IndexKeys.Ascending(b => b.Name);
await collection.Indexes.CreateOneAsync(new CreateIndexModel<Book>(indexKeys));
return await base.GetQueryableAsync();
}
}
GetCancellationToken(cancellationToken) for proper cancellationdevelopment
This skill enables visual inspection of websites running locally or remotely to identify and fix design issues. Triggers on requests like "review website design", "check the UI", "fix the layout", "find design problems". Detects issues with responsive design, accessibility, visual consistency, and layout breakage, then performs fixes at the source code level.
testing
Comprehensive unit testing with xUnit, mocking, test patterns, and best practices for .NET applications
data-ai
Universal SQL performance optimization assistant for comprehensive query tuning, indexing strategies, and database performance analysis across all SQL databases (MySQL, PostgreSQL, SQL Server, Oracle). Provides execution plan analysis, pagination optimization, batch operations, and performance monitoring guidance.
development
Universal SQL code review assistant that performs comprehensive security, maintainability, and code quality analysis across all SQL databases (MySQL, PostgreSQL, SQL Server, Oracle). Focuses on SQL injection prevention, access control, code standards, and anti-pattern detection. Complements SQL optimization prompt for complete development coverage.