Refactor domain layer to follow Clean Architecture
Updated the domain layer to align with Clean Architecture principles: - Removed Entity Framework dependencies from the project. - Updated AGENTS.md to document the new architecture. - Introduced repository interfaces for data access abstraction. - Added a generic IRepository interface for CRUD operations. - Implemented entity-specific repositories for Profile, ProfileSqlJob, and ProfileHistory. - Ensured the domain layer is infrastructure-independent with pure POCOs. - Updated project structure and documentation for clarity.
This commit is contained in:
@@ -2,7 +2,12 @@
|
||||
|
||||
## Project Overview
|
||||
|
||||
ECMJobRunner.Domain is a domain entity library for the ECM Job Runner system. This project contains entity models that represent the database schema for job runner configuration and execution history.
|
||||
ECMJobRunner.Domain is the **domain layer** for the ECM Job Runner system following **Clean Architecture** principles. This project contains:
|
||||
- **Entity models** that represent the business domain
|
||||
- **Repository interfaces** for data access abstraction
|
||||
- **Domain logic** (currently none, pure data entities)
|
||||
|
||||
**Key Principle**: This layer has **NO** external dependencies - it's the core of the application.
|
||||
|
||||
## Target Frameworks
|
||||
|
||||
@@ -11,11 +16,13 @@ ECMJobRunner.Domain is a domain entity library for the ECM Job Runner system. Th
|
||||
|
||||
The project is multi-targeted to support both legacy .NET Framework applications and modern .NET 8 applications.
|
||||
|
||||
## Technologies
|
||||
## Architecture
|
||||
|
||||
### Entity Framework
|
||||
- **For .NET Framework 4.8**: Entity Framework 6.5.1
|
||||
- **For .NET 8.0**: Entity Framework Core 8.0.11 with SQL Server provider
|
||||
This project follows **Clean Architecture** principles:
|
||||
- **No infrastructure dependencies** (no Entity Framework, no database concerns)
|
||||
- **Pure domain entities** without ORM attributes
|
||||
- **Repository pattern interfaces** for data access abstraction
|
||||
- **Dependency inversion** - infrastructure depends on domain, not vice versa
|
||||
|
||||
## Project Structure
|
||||
|
||||
@@ -25,6 +32,12 @@ ECMJobRunner.Domain/
|
||||
│ ├── Profile.cs # Job configuration profile entity
|
||||
│ ├── ProfileSqlJob.cs # SQL job configuration entity
|
||||
│ └── ProfileHistory.cs # Job execution history entity
|
||||
├── Interfaces/
|
||||
│ ├── IRepository.cs # Generic repository interface
|
||||
│ ├── IProfileRepository.cs # Profile-specific repository
|
||||
│ ├── IProfileSqlJobRepository.cs
|
||||
│ ├── IProfileHistoryRepository.cs
|
||||
│ └── IUnitOfWork.cs # Unit of Work pattern interface
|
||||
├── ECMJobRunner.Domain.csproj
|
||||
└── AGENTS.md # This file
|
||||
```
|
||||
@@ -32,96 +45,105 @@ ECMJobRunner.Domain/
|
||||
## Entities
|
||||
|
||||
### Profile
|
||||
**Table:** `dbo.TBJR_CFG_PROFILE`
|
||||
|
||||
Represents a job runner profile configuration.
|
||||
|
||||
**Key Properties:**
|
||||
- `Id` (PK): Primary key, auto-generated
|
||||
- `Active`: Enable/disable switch
|
||||
- `ProfileName`: Name of the profile
|
||||
- `TypeId`: Profile type (0=ADSync, 1=GraphQL, 2=SQL-Job, 3=SQL and REST-Job)
|
||||
- `Schedule`: Cron format schedule
|
||||
- `Comment`: Optional description
|
||||
**Properties:**
|
||||
- `Id` (long): Primary key
|
||||
- `Active` (bool): Enable/disable switch
|
||||
- `ProfileName` (string, max 150): Name of the profile
|
||||
- `TypeId` (byte): Profile type (0=ADSync, 1=GraphQL, 2=SQL-Job, 3=SQL and REST-Job)
|
||||
- `Schedule` (string, max 150): Cron format schedule
|
||||
- `Comment` (string?, max 500): Optional description
|
||||
- `AddedWho`, `AddedWhen`, `ChangedWho`, `ChangedWhen`: Audit fields
|
||||
|
||||
**Relationships:**
|
||||
- One-to-Many with `ProfileSqlJob` (SQL jobs)
|
||||
- One-to-Many with `ProfileHistory` (execution history)
|
||||
**Navigation Properties:**
|
||||
- `SqlJobs` (IEnumerable<ProfileSqlJob>?): Associated SQL jobs
|
||||
- `ProfileHistories` (IEnumerable<ProfileHistory>?): Execution history
|
||||
|
||||
### ProfileSqlJob
|
||||
**Table:** `dbo.TBJR_CFG_PROFILE_SQLJOB`
|
||||
|
||||
Represents individual SQL jobs within a profile.
|
||||
|
||||
**Key Properties:**
|
||||
- `Id` (PK): Primary key, auto-generated
|
||||
- `ProfileId` (FK): Foreign key to `Profile`
|
||||
- `Active`: Enable/disable switch
|
||||
- `Sequence`: Execution order within the profile
|
||||
- `Name`: Optional job name
|
||||
- `SqlCheckQuery`: SQL query for pre-check
|
||||
- `SqlMainQuery`: Main SQL query
|
||||
- `ApiCommand`: API command to execute
|
||||
**Properties:**
|
||||
- `Id` (long): Primary key
|
||||
- `ProfileId` (long): Foreign key to Profile
|
||||
- `Active` (bool): Enable/disable switch
|
||||
- `Sequence` (short): Execution order within the profile
|
||||
- `Name` (string?, max 150): Optional job name
|
||||
- `SqlCheckQuery` (string?): SQL query for pre-check
|
||||
- `SqlMainQuery` (string?): Main SQL query
|
||||
- `ApiCommand` (string?): API command to execute
|
||||
- `Comment` (string?, max 500): Optional description
|
||||
- Audit fields
|
||||
|
||||
**Relationships:**
|
||||
- Many-to-One with `Profile`
|
||||
**Navigation Properties:**
|
||||
- `Profile` (Profile?): Associated profile
|
||||
|
||||
### ProfileHistory
|
||||
**Table:** `dbo.TBJR_OUT_PROFILE_HISTORY`
|
||||
|
||||
Stores execution history and results of job profiles.
|
||||
|
||||
**Key Properties:**
|
||||
- `Id` (PK): Primary key, auto-generated
|
||||
- `ProfileId` (FK): Foreign key to `Profile`
|
||||
- `ResultId`: Result status (0=OK, 1=ERROR, 2=WARNING)
|
||||
- `ResultText`: Result message/details
|
||||
**Properties:**
|
||||
- `Id` (long): Primary key
|
||||
- `ProfileId` (long): Foreign key to Profile
|
||||
- `ResultId` (byte): Result status (0=OK, 1=ERROR, 2=WARNING)
|
||||
- `ResultText` (string): Result message/details
|
||||
- Audit fields
|
||||
|
||||
**Relationships:**
|
||||
- Many-to-One with `Profile`
|
||||
**Navigation Properties:**
|
||||
- `Profile` (Profile?): Associated profile
|
||||
|
||||
## Repository Interfaces
|
||||
|
||||
### IRepository<TEntity>
|
||||
Generic repository interface providing CRUD operations:
|
||||
- `GetById(id)`, `GetByIdAsync(id)`
|
||||
- `GetAll()`, `GetAllAsync()`
|
||||
- `Find(predicate)`, `FindAsync(predicate)`
|
||||
- `SingleOrDefault(predicate)`, `SingleOrDefaultAsync(predicate)`
|
||||
- `Add(entity)`, `AddRange(entities)`
|
||||
- `Update(entity)`, `Remove(entity)`, `RemoveRange(entities)`
|
||||
|
||||
### Entity-Specific Repositories
|
||||
- `IProfileRepository : IRepository<Profile>`
|
||||
- `IProfileSqlJobRepository : IRepository<ProfileSqlJob>`
|
||||
- `IProfileHistoryRepository : IRepository<ProfileHistory>`
|
||||
|
||||
### IUnitOfWork
|
||||
Manages transactions and provides access to all repositories:
|
||||
- `Profiles`: IProfileRepository
|
||||
- `ProfileSqlJobs`: IProfileSqlJobRepository
|
||||
- `ProfileHistories`: IProfileHistoryRepository
|
||||
- `SaveChanges()`, `SaveChangesAsync()`
|
||||
|
||||
## Database Schema Source
|
||||
|
||||
The entities are based on SQL Server tables located at:
|
||||
The entities map to SQL Server tables located at:
|
||||
```
|
||||
M:\Datenbank\[DD_ECM]-Database\JobRunner\
|
||||
```
|
||||
|
||||
The following SQL files define the schema:
|
||||
- `[TBJR_CFG_PROFILE].sql` - Profile configuration table
|
||||
- `[TBJR_CFG_PROFILE_SQLJOB].sql` - SQL job configuration table
|
||||
- `[TBJR_OUT_PROFILE_HISTORY].sql` - Execution history table
|
||||
- `[VWJR_CFG_PROFILE].sql` - Profile view (not implemented as entity)
|
||||
- `[VWJR_CFG_PROFILE_SQLJOB].sql` - SQL job view (not implemented as entity)
|
||||
**Table Mappings** (handled in Infrastructure layer):
|
||||
- `Profile` → `dbo.TBJR_CFG_PROFILE`
|
||||
- `ProfileSqlJob` → `dbo.TBJR_CFG_PROFILE_SQLJOB`
|
||||
- `ProfileHistory` → `dbo.TBJR_OUT_PROFILE_HISTORY`
|
||||
|
||||
## Naming Conventions
|
||||
|
||||
- **Entity Classes**: Clean Pascal case (e.g., `Profile` instead of `TBJR_CFG_PROFILE`)
|
||||
- **Properties**: Pascal case (e.g., `ProfileName` instead of `PROFILE_NAME`)
|
||||
- **Table Mapping**: Uses `[Table]` attribute to map to actual database table names
|
||||
- **Column Mapping**: Uses `[Column]` attribute to map to actual column names
|
||||
- Entity names are simplified without technical prefixes (Jr/Cfg/Out)
|
||||
- **No ORM attributes** - entities are pure POCOs
|
||||
- **Navigation properties** are nullable `IEnumerable<T>?` (loaded only when explicitly included)
|
||||
|
||||
## Attributes Used
|
||||
## Dependencies
|
||||
|
||||
- `[Table]` - Specifies the database table name and schema
|
||||
- `[Column]` - Specifies the database column name
|
||||
- `[Key]` - Marks the primary key
|
||||
- `[Required]` - Marks non-nullable properties
|
||||
- `[MaxLength]` - Specifies maximum string length
|
||||
- `[ForeignKey]` - Specifies foreign key relationships
|
||||
- `[DatabaseGenerated]` - Specifies identity/auto-generated columns
|
||||
**NONE** - This is a core domain layer with zero external dependencies.
|
||||
|
||||
## Building the Project
|
||||
|
||||
To build the project:
|
||||
|
||||
```bash
|
||||
dotnet build ECMJobRunner.Domain.csproj
|
||||
```
|
||||
|
||||
To build for a specific framework:
|
||||
|
||||
For specific framework:
|
||||
```bash
|
||||
dotnet build ECMJobRunner.Domain.csproj -f net8.0
|
||||
dotnet build ECMJobRunner.Domain.csproj -f net480
|
||||
@@ -129,11 +151,16 @@ dotnet build ECMJobRunner.Domain.csproj -f net480
|
||||
|
||||
## Development Notes
|
||||
|
||||
- All entities include audit fields: `AddedWho`, `AddedWhen`, `ChangedWho`, `ChangedWhen`
|
||||
- Navigation properties are marked as `virtual` to support lazy loading
|
||||
- Nullable reference types are enabled for better null-safety
|
||||
- XML documentation is generated for IntelliSense support
|
||||
- Default values are set according to database constraints
|
||||
- **Clean Architecture**: Domain layer is independent of infrastructure concerns
|
||||
- **Navigation properties**: Nullable IEnumerable - populated only when explicitly loaded via `.Include()`
|
||||
- **No ORM attributes**: Pure POCOs - mapping is done in Infrastructure layer
|
||||
- **Repository pattern**: All data access through interfaces
|
||||
- **Unit of Work pattern**: Transaction management abstraction
|
||||
|
||||
## Related Projects
|
||||
|
||||
- **ECMJobRunner.Infrastructure**: Implements repositories and DbContext
|
||||
- **ECMJobRunner.Application**: Application layer with business logic
|
||||
|
||||
## Company Information
|
||||
|
||||
|
||||
Reference in New Issue
Block a user