Files
ECMJobRunner/ECMJobRunner.Infrastructure/AGENTS.md
TekH 7d53b599de Add Infrastructure layer with EF6/EF Core support
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.
2026-07-09 13:35:02 +02:00

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