fluentcms / fluentcms/FluentCMS
🚀 Feature: Implement Database-Agnostic Repository Layer with Type-Safe Fluent Queries
- Dominant language
- C#
- Stars
- 565
- Forks
- 107
- PR merge metrics
- No merged PRs in 30d
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**
```csharp
// Generic repository interface
public interface IRepository : IRepository where TEntity : class, IEntity
{
// CRUD operations
Task Add(TEntity entity, CancellationToken cancellationToken = default);
Task> AddRange(IEnumerable entities, CancellationToken cancellationToken = default);
Task Update(TEntity entity, CancellationToken cancellationToken = default);
Task Remove(Guid id, CancellationToken cancellationToken = default);
// Bulk operations
Task UpdateRange(ISpecification specification, Expression> updateExpression, CancellationToken cancellationToken = default);
Task RemoveRange(ISpecification specification, CancellationToken cancellationToken = default);
// Query operations
Task> Query(ISpecification specification, CancellationToken cancellationToken = default);
Task> FindPaged(IFluentOrderedQuery orderedQuery, int page, int pageSize, CancellationToken cancellationToken = default);
}
// Fluent query interfaces
public interface IFluentQuery where T : class
{
IFluentQuery Where(Expression> predicate);
IFluentOrderedQuery OrderBy(Expression> keySelector);
IFluentOrderedQuery OrderByDescending(Expression> keySelector);
// No Skip/Take here - forces ordering first!
}
public interface IFluentOrderedQuery : IFluentQuery where T : class
{
IFluentOrderedQuery ThenBy(Expression> keySelector);
IFluentOrderedQuery Skip(int count); // Only available after ordering!
IFluentOrderedQuery Take(int count); // Only available after ordering!
}
```
### **Database Management**
```csharp
// Database-agnostic connection management
public interface IDatabaseManager : IDatabaseManager where T : IDatabaseManagerMarker
{
string ConnectionString { get; }
Task EntitySetsExist(IEnumerable entitySetNames, CancellationToken cancellationToken = default);
}
// Database initialization
public interface IDataSeeder
{
int Priority { get; }
Task HasData(CancellationToken cancellationToken = default);
Task SeedData(CancellationToken cancellationToken = default);
}
public interface ISchemaValidator
{
int Priority { get; }
Task ValidateSchema(CancellationToken cancellationToken = default);
Task CreateSchema(CancellationToken cancellationToken = default);
}
```
## 💡 Key Benefits
### **1. Compile-Time Ordering Safety**
```csharp
// ✅ 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!
```
### **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** ✅
- [x] `IRepository` interface with CRUD operations
- [x] `IFluentQuery` and `IFluentOrderedQuery` interfaces
- [x] `ISpecification` pattern implementation
- [x] Database manager interfaces
- [x] Bulk operations support
- [x] 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**
```csharp
// 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**
```csharp
// Bulk update
var specification = new ExpressionSpecification(x => x.IsActive == false);
await userRepository.UpdateRange(specification, x => x with { LastLoginDate = DateTime.UtcNow });
// Bulk delete
await userRepository.RemoveRange(specification);
```
### **Database Switching**
```csharp
// Configuration-driven database selection
services.AddDatabaseManager(options =>
{
options.MapLibrary().UseSqlServer(connectionString);
options.MapLibrary().UseMongoDB(mongoConnectionString);
options.MapLibrary().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.
Contributor guide
Assessment
This issue has not been assessed yet.