-
Notifications
You must be signed in to change notification settings - Fork 105
Open
Open
Copy link
Labels
databaseenhancementNew feature or requestNew feature or requestfeature-requestinfrastructurerepository-pattern
Milestone
Description
🎯 Feature Request
Implement a comprehensive database-agnostic repository abstraction layer that supports multiple database types (RDBMS via EF Core, MongoDB, LiteDB) with type-safe fluent query interfaces and compile-time ordering validation.
📋 Proposed Implementation
Core Abstractions
// Generic repository interface
public interface IRepository<TEntity> : IRepository where TEntity : class, IEntity
{
// CRUD operations
Task<TEntity> Add(TEntity entity, CancellationToken cancellationToken = default);
Task<IEnumerable<TEntity>> AddRange(IEnumerable<TEntity> entities, CancellationToken cancellationToken = default);
Task<TEntity> Update(TEntity entity, CancellationToken cancellationToken = default);
Task<TEntity?> Remove(Guid id, CancellationToken cancellationToken = default);
// Bulk operations
Task<int> UpdateRange(ISpecification<TEntity> specification, Expression<Func<TEntity, TEntity>> updateExpression, CancellationToken cancellationToken = default);
Task<int> RemoveRange(ISpecification<TEntity> specification, CancellationToken cancellationToken = default);
// Query operations
Task<IEnumerable<TEntity>> Query(ISpecification<TEntity> specification, CancellationToken cancellationToken = default);
Task<IPagedResult<TEntity>> FindPaged(IFluentOrderedQuery<TEntity> orderedQuery, int page, int pageSize, CancellationToken cancellationToken = default);
}
// Fluent query interfaces
public interface IFluentQuery<T> where T : class
{
IFluentQuery<T> Where(Expression<Func<T, bool>> predicate);
IFluentOrderedQuery<T> OrderBy<TKey>(Expression<Func<T, TKey>> keySelector);
IFluentOrderedQuery<T> OrderByDescending<TKey>(Expression<Func<T, TKey>> keySelector);
// No Skip/Take here - forces ordering first!
}
public interface IFluentOrderedQuery<T> : IFluentQuery<T> where T : class
{
IFluentOrderedQuery<T> ThenBy<TKey>(Expression<Func<T, TKey>> keySelector);
IFluentOrderedQuery<T> Skip(int count); // Only available after ordering!
IFluentOrderedQuery<T> Take(int count); // Only available after ordering!
}Database Management
// Database-agnostic connection management
public interface IDatabaseManager<T> : IDatabaseManager where T : IDatabaseManagerMarker
{
string ConnectionString { get; }
Task<bool> EntitySetsExist(IEnumerable<string> entitySetNames, CancellationToken cancellationToken = default);
}
// Database initialization
public interface IDataSeeder
{
int Priority { get; }
Task<bool> HasData(CancellationToken cancellationToken = default);
Task SeedData(CancellationToken cancellationToken = default);
}
public interface ISchemaValidator
{
int Priority { get; }
Task<bool> ValidateSchema(CancellationToken cancellationToken = default);
Task CreateSchema(CancellationToken cancellationToken = default);
}💡 Key Benefits
1. Compile-Time Ordering Safety
// ✅ This compiles - proper ordering
var pagedResults = await repo.Query()
.Where(x => x.IsActive)
.OrderBy(x => x.CreatedDate)
.Skip(20)
.Take(10)
.Query();
// ❌ This won't compile - no ordering
var invalid = repo.Query()
.Where(x => x.IsActive)
.Skip(20); // Compile error: Skip not available on IFluentQuery<T>!2. Database-Agnostic Design
- Consistent API across RDBMS, MongoDB, and LiteDB
- Easy database switching without code changes
- Database-specific optimizations under the hood
3. Enhanced Developer Experience
- IntelliSense-guided query building
- Fluent API similar to LINQ
- Immediate execution capabilities
- No runtime ordering errors
4. Performance Features
- Bulk operations for mass data changes
- Efficient pagination with guaranteed ordering
- Expression-based query building
- Immutable query construction
🔧 Technical Specifications
- Target Framework: .NET 9
- Pattern: Repository + Specification + Fluent Query
- Database Support:
- EF Core (SQL Server, PostgreSQL, MySQL, SQLite)
- MongoDB (Document database)
- LiteDB (Embedded database)
- Features: Async/await throughout, comprehensive cancellation token support
- Architecture: Immutable query building, expression-based specifications
📝 Implementation Phases
Phase 1: Core Abstractions ✅
-
IRepository<TEntity>interface with CRUD operations -
IFluentQuery<T>andIFluentOrderedQuery<T>interfaces -
ISpecification<T>pattern implementation - Database manager interfaces
- Bulk operations support
- Extension methods for fluent API
Phase 2: Database Implementations
-
EF Core Repository
- DbContext integration
- Transaction support
- Change tracking optimization
- Include/ThenInclude support
-
MongoDB Repository
- MongoDB.Driver integration
- Aggregation pipeline support
- Document-specific optimizations
- GridFS support for file storage
-
LiteDB Repository
- Embedded database scenarios
- File-based storage
- Lightweight transaction support
- Cross-platform compatibility
Phase 3: Advanced Features
- Multi-database transaction coordination
- Query caching layer
- Performance monitoring and metrics
- Database migration tools
- Connection pooling optimization
📊 Usage Examples
Basic Usage
// Simple query
var activeUsers = await userRepository.Query()
.Where(x => x.IsActive)
.Query();
// Complex ordered query with pagination
var pagedUsers = await userRepository.Query()
.Where(x => x.Role == "Manager")
.Where(x => x.IsActive)
.OrderBy(x => x.Name)
.ThenBy(x => x.CreatedDate)
.Skip(20)
.Take(10)
.Query();
// Type-safe pagination
var orderedQuery = userRepository.Query()
.Where(x => x.IsActive)
.OrderBy(x => x.CreatedDate);
var pagedResult = await userRepository.FindPaged(orderedQuery, page: 1, pageSize: 10);Bulk Operations
// Bulk update
var specification = new ExpressionSpecification<User>(x => x.IsActive == false);
await userRepository.UpdateRange(specification, x => x with { LastLoginDate = DateTime.UtcNow });
// Bulk delete
await userRepository.RemoveRange(specification);Database Switching
// Configuration-driven database selection
services.AddDatabaseManager(options =>
{
options.MapLibrary<IUserLibraryMarker>().UseSqlServer(connectionString);
options.MapLibrary<IProductLibraryMarker>().UseMongoDB(mongoConnectionString);
options.MapLibrary<ICacheLibraryMarker>().UseLiteDB(liteDbPath);
});✅ Acceptance Criteria
- Core abstractions implemented with comprehensive interfaces
- EF Core repository with transaction support
- MongoDB repository with aggregation pipeline support
- LiteDB repository for embedded scenarios
- Compile-time ordering validation working correctly
- Bulk operations implemented for all database types
- Extension methods providing fluent API experience
- Unit tests achieving 90%+ code coverage
- Integration tests for all database implementations
- Performance benchmarks comparing database types
- Comprehensive documentation with examples
- Database migration and seeding tools
🧪 Testing Strategy
- Unit Tests: Core abstractions, query building, specifications
- Integration Tests: Database implementations, transaction scenarios
- Performance Tests: Bulk operations, pagination, complex queries
- Compatibility Tests: Cross-platform, different database versions
📚 Documentation Needs
- Architecture overview and design decisions
- Getting started guide for each database type
- Advanced usage patterns and best practices
- Migration guide from existing data access patterns
- Performance tuning recommendations
- Troubleshooting guide
🔗 Related Issues
- Database connection management
- Schema migration tools
- Performance monitoring integration
- Multi-tenant database support
Priority: High
Complexity: Medium-High
Estimated Effort: 3-4 weeks
Dependencies: None
This implementation will provide FluentCMS with a robust, type-safe, and database-agnostic data access layer that supports modern development practices while maintaining excellent performance across different database technologies.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
databaseenhancementNew feature or requestNew feature or requestfeature-requestinfrastructurerepository-pattern