Перейти к содержанию

Структура решения

В практике используется единое решение ActivityMonitoring. Оно разделено на четыре слоя.

Схема ниже нужна как карта проекта: по ней видно, в каком проекте должен лежать каждый тип файла и почему контроллеры, сущности и работа с базой не смешиваются в одной папке.

ActivityMonitoring/
  ActivityMonitoring.Api/              # Presentation: контроллеры, JWT, DI, Program.cs
  ActivityMonitoring.Application/      # сервисы, DTO, интерфейсы, аналитика
  ActivityMonitoring.Domain/           # сущности, enum, доменные правила
  ActivityMonitoring.Infrastructure/   # EF Core, репозитории, отчёты, генератор событий

Назначение слоёв

Слой За что отвечает Что не должен делать
Domain Сущности и правила предметной области Не работает с HTTP, EF Core и файлами
Application Сценарии использования, DTO, сервисы Не знает конкретную СУБД
Infrastructure База данных, репозитории, отчёты, внешние реализации Не содержит HTTP-контроллеры
Api REST API, авторизация, маршруты, Swagger Не хранит бизнес-логику в контроллерах

Зависимости проектов

Этот блок показывает разрешённые направления ссылок между проектами. Зависимости идут от внешних слоёв к внутренним: API может знать о сервисах, а доменная модель не должна знать ни о вебе, ни о базе данных.

Api -> Application
Api -> Infrastructure
Infrastructure -> Application
Infrastructure -> Domain
Application -> Domain
Domain -> ни от кого не зависит

Такая схема позволяет заменить SQLite на PostgreSQL или MS SQL без переписывания контроллеров и бизнес-логики.

Основные сущности

Диаграмма фиксирует минимальную предметную модель. Она помогает заранее понять, почему событие связано с пользователем, а пользователь — с ролью, и какие таблицы появятся после миграции.

erDiagram
    APP_USER ||--o{ ACTIVITY_EVENT : creates
    ROLE ||--o{ APP_USER : assigned

    ROLE {
        int Id
        string Name
    }

    APP_USER {
        int Id
        string UserName
        string PasswordHash
        int RoleId
        bool IsActive
    }

    ACTIVITY_EVENT {
        int Id
        int UserId
        string Type
        string Source
        string Description
        string Severity
        datetime CreatedAt
    }

Поток выполнения запроса

Последовательность ниже объясняет, зачем в проекте нужны все слои сразу. Один HTTP-запрос проходит через контроллер, сервис, репозиторий и DbContext, а каждый участник выполняет только свою часть работы.

sequenceDiagram
    participant Client as Клиент
    participant Api as EventsController
    participant Service as ActivityEventService
    participant Repo as Repository
    participant Db as EF Core DbContext

    Client->>Api: POST /api/events
    Api->>Service: CreateAsync(dto, userId)
    Service->>Service: Валидация и бизнес-правила
    Service->>Repo: AddAsync(entity)
    Repo->>Db: SaveChangesAsync()
    Db-->>Repo: Id события
    Repo-->>Service: entity
    Service-->>Api: EventDto
    Api-->>Client: 201 Created