Introduced a robust Infrastructure layer for the ECMJobRunner system: - Added `AGENTS.md` with detailed project documentation. - Implemented generic repository and unit-of-work patterns. - Added `CfgProfileRepository`, `ProfileSqlJobRepository`, and `ProfileHistoryRepository`. - Integrated AutoMapper for DTO-to-entity mapping. - Added multi-framework support for .NET Framework 4.8 (EF6) and .NET 8.0 (EF Core) using conditional compilation. - Updated `ECMJobRunner.Infrastructure.csproj` with metadata fixes and dependencies. - Introduced dependency injection extension for .NET 8.0. - Enhanced project structure and database context with entity mappings.
206 lines
6.2 KiB
Markdown
206 lines
6.2 KiB
Markdown
# ECMJobRunner.Infrastructure
|
|
|
|
## Project Overview
|
|
|
|
ECMJobRunner.Infrastructure is the **infrastructure layer** for the ECM Job Runner system following **Clean Architecture** principles. This project contains:
|
|
- **DbContext implementation** with Entity Framework
|
|
- **Repository implementations** for data access
|
|
- **Entity configurations** (EF mappings)
|
|
- **Database connection management**
|
|
|
|
**Key Principle**: This layer implements the interfaces defined in the Domain layer and handles all database concerns.
|
|
|
|
## Target Frameworks
|
|
|
|
- **.NET Framework 4.8** (`net480`) - Uses **Entity Framework 6.5.1**
|
|
- **.NET 8.0** (`net8.0`) - Uses **Entity Framework Core 8.0.11**
|
|
|
|
The project uses conditional compilation to support both EF6 and EF Core with the same codebase.
|
|
|
|
## Architecture
|
|
|
|
This project follows **Clean Architecture** principles:
|
|
- **Depends on Domain layer** (implements domain interfaces)
|
|
- **No dependencies from Domain** (dependency inversion)
|
|
- **Conditional compilation** for EF6 vs EF Core differences
|
|
- **Repository pattern** implementation
|
|
- **Unit of Work pattern** implementation
|
|
|
|
## Project Structure
|
|
|
|
```
|
|
ECMJobRunner.Infrastructure/
|
|
├── Data/
|
|
│ └── JobRunnerDbContext.cs # DbContext with conditional compilation
|
|
├── Repositories/
|
|
│ ├── Repository.cs # Generic repository implementation
|
|
│ ├── ProfileRepository.cs # Profile-specific repository
|
|
│ ├── ProfileSqlJobRepository.cs
|
|
│ ├── ProfileHistoryRepository.cs
|
|
│ └── UnitOfWork.cs # Unit of Work implementation
|
|
├── ECMJobRunner.Infrastructure.csproj
|
|
└── AGENTS.md # This file
|
|
```
|
|
|
|
## Database Context
|
|
|
|
### JobRunnerDbContext
|
|
|
|
Multi-targeted DbContext supporting both EF6 and EF Core:
|
|
|
|
**DbSets:**
|
|
- `Profiles`: DbSet<Profile>
|
|
- `ProfileSqlJobs`: DbSet<ProfileSqlJob>
|
|
- `ProfileHistories`: DbSet<ProfileHistory>
|
|
|
|
**Configuration:**
|
|
- Connection string via constructor parameter
|
|
- Conditional compilation directives (`#if NET48` / `#else`)
|
|
- Fluent API configurations in `OnModelCreating`
|
|
|
|
**Table Mappings:**
|
|
- `Profile` → `dbo.TBJR_CFG_PROFILE`
|
|
- `ProfileSqlJob` → `dbo.TBJR_CFG_PROFILE_SQLJOB`
|
|
- `ProfileHistory` → `dbo.TBJR_OUT_PROFILE_HISTORY`
|
|
|
|
**Column Mappings:** (Examples)
|
|
- `Profile.ProfileName` → `PROFILE_NAME`
|
|
- `ProfileSqlJob.SqlCheckQuery` → `SQL_CHECK_QUERY`
|
|
- All navigation properties configured with relationships
|
|
|
|
## Repository Implementations
|
|
|
|
### Repository<TEntity>
|
|
Generic repository implementing `IRepository<TEntity>` with full CRUD operations.
|
|
|
|
**Key Methods:**
|
|
- Synchronous: `GetById`, `GetAll`, `Find`, `SingleOrDefault`, `Add`, `Update`, `Remove`
|
|
- Asynchronous: `GetByIdAsync`, `GetAllAsync`, `FindAsync`, `SingleOrDefaultAsync`
|
|
|
|
### Entity-Specific Repositories
|
|
- `ProfileRepository : Repository<Profile>, IProfileRepository`
|
|
- `ProfileSqlJobRepository : Repository<ProfileSqlJob>, IProfileSqlJobRepository`
|
|
- `ProfileHistoryRepository : Repository<ProfileHistory>, IProfileHistoryRepository`
|
|
|
|
These can be extended with entity-specific query methods as needed.
|
|
|
|
### UnitOfWork
|
|
Implements `IUnitOfWork` interface:
|
|
- Manages DbContext lifecycle
|
|
- Provides repository instances
|
|
- Handles transaction management via `SaveChanges`/`SaveChangesAsync`
|
|
|
|
## Connection String
|
|
|
|
Default connection string (configured in consuming applications):
|
|
```
|
|
Server=SDD-VMP04-SQL17\DD_DEVELOP01;Database=DD_ECM;User Id=sa;Password=dd;Encrypt=false;TrustServerCertificate=True;
|
|
```
|
|
|
|
## Database Schema Source
|
|
|
|
SQL scripts and schema definitions are located at:
|
|
```
|
|
M:\Datenbank\[DD_ECM]-Database\JobRunner\
|
|
```
|
|
|
|
## Dependencies
|
|
|
|
### .NET Framework 4.8 (`net480`)
|
|
- **ECMJobRunner.Domain** (project reference)
|
|
- **EntityFramework 6.5.1** (NuGet package)
|
|
|
|
### .NET 8.0 (`net8.0`)
|
|
- **ECMJobRunner.Domain** (project reference)
|
|
- **Microsoft.EntityFrameworkCore 8.0.11** (NuGet package)
|
|
- **Microsoft.EntityFrameworkCore.SqlServer 8.0.11** (NuGet package)
|
|
|
|
## Conditional Compilation
|
|
|
|
The project uses `#if NET48` / `#else` directives to handle differences between EF6 and EF Core:
|
|
|
|
**EF6 (.NET Framework 4.8):**
|
|
```csharp
|
|
#if NET48
|
|
using System.Data.Entity;
|
|
public class JobRunnerDbContext : DbContext
|
|
#endif
|
|
```
|
|
|
|
**EF Core (.NET 8.0):**
|
|
```csharp
|
|
#if !NET48
|
|
using Microsoft.EntityFrameworkCore;
|
|
public class JobRunnerDbContext : DbContext
|
|
#endif
|
|
```
|
|
|
|
## Building the Project
|
|
|
|
```bash
|
|
dotnet build ECMJobRunner.Infrastructure.csproj
|
|
```
|
|
|
|
For specific framework:
|
|
```bash
|
|
dotnet build ECMJobRunner.Infrastructure.csproj -f net8.0
|
|
dotnet build ECMJobRunner.Infrastructure.csproj -f net480
|
|
```
|
|
|
|
## Entity Framework Differences
|
|
|
|
### DbContext Constructor
|
|
- **EF6**: Accepts connection string directly
|
|
- **EF Core**: Requires `DbContextOptions<T>`
|
|
|
|
### Configuration
|
|
- **EF6**: `DbModelBuilder` in `OnModelCreating`
|
|
- **EF Core**: `ModelBuilder` in `OnModelCreating`
|
|
|
|
### Querying
|
|
- **EF6**: `DbSet<T>.AsNoTracking()` extension
|
|
- **EF Core**: Same API, built-in support
|
|
|
|
### Async Operations
|
|
- **EF6**: Limited async support
|
|
- **EF Core**: Full async/await support
|
|
|
|
## Development Notes
|
|
|
|
- **Nullable navigation properties**: `IEnumerable<T>?` to support defensive programming
|
|
- **No lazy loading**: Navigation properties loaded explicitly via `.Include()`
|
|
- **Transaction management**: Handled by Unit of Work pattern
|
|
- **Repository pattern**: Encapsulates EF-specific code
|
|
- **Clean Architecture**: Infrastructure depends on Domain, not vice versa
|
|
|
|
## Usage Example
|
|
|
|
```csharp
|
|
// Create DbContext (connection string from configuration)
|
|
var connectionString = ConfigurationManager.ConnectionStrings["JobRunner"].ConnectionString;
|
|
var context = new JobRunnerDbContext(connectionString);
|
|
|
|
// Use Unit of Work
|
|
using var unitOfWork = new UnitOfWork(context);
|
|
|
|
// Query profiles
|
|
var activeProfiles = await unitOfWork.Profiles
|
|
.FindAsync(p => p.Active);
|
|
|
|
// Add new profile
|
|
var profile = new Profile { ProfileName = "Test", Active = true };
|
|
unitOfWork.Profiles.Add(profile);
|
|
await unitOfWork.SaveChangesAsync();
|
|
```
|
|
|
|
## Related Projects
|
|
|
|
- **ECMJobRunner.Domain**: Contains entities and repository interfaces
|
|
- **ECMJobRunner.Application**: Application layer consuming repositories
|
|
|
|
## Company Information
|
|
|
|
**Author**: Digital Data GmbH
|
|
**Copyright**: 2026
|
|
**Repository**: http://git.dd:3000/AppStd/ECMJobRunner.git
|