> ## Documentation Index
> Fetch the complete documentation index at: https://docs.diyanet.pro/llms.txt
> Use this file to discover all available pages before exploring further.

# Data Katmanı — Genel Bakış

> EF Core (PostgreSQL 16 + Npgsql + snake_case), DbContext, migration, audit, soft-delete ve seed

`DiyanetCleanArchitecture.Infrastructure.EFCore` projesi persistence (kalıcılık) katmanıdır. Domain aggregate'lerini PostgreSQL'e map eder, migration'ları üretir/uygular, audit + soft-delete davranışını tek bir interceptor üzerinden otomatikleştirir ve başlangıç verisini (seed) yazar.

## Rolü

* **Tek DbContext:** `DiyanetCleanArchitectureDbContext : DbContext, IUnitOfWork` — tüm aggregate'lerin `DbSet`'leri burada.
* **EntityTypeConfiguration'lar:** Her aggregate için ayrı `IEntityTypeConfiguration<T>` (Fluent API). `OnModelCreating` bunları assembly'den reflection ile toplar.
* **Migration'lar:** `Migrations/` klasörü — EF Core code-first.
* **Interceptor:** `AuditInterceptor : SaveChangesInterceptor` — `CreatedAt/By`, `UpdatedAt/By`, soft-delete.
* **Repository'ler:** `EFRepository<T>` (write, `Ardalis.Specification` tabanlı), `CachedRepository<T>` (read, HybridCache decorator).
* **Seed servisleri:** `DevDataSeeder` (bootstrap admin), `DistrictSeeder` (973 ilçe), Fluent `HasData` (Role/RolePermission/Permission).

## Teknoloji

| Bileşen       | Seçim                                                                |
| ------------- | -------------------------------------------------------------------- |
| Veritabanı    | PostgreSQL 16 (dev: docker `postgres:16`)                            |
| Provider      | `Npgsql.EntityFrameworkCore.PostgreSQL` 10.0.1                       |
| EF Core       | 10.0.7                                                               |
| Naming        | `EFCore.NamingConventions` 10.0.1 → `UseSnakeCaseNamingConvention()` |
| Specification | `Ardalis.Specification.EntityFrameworkCore` 9.3.1                    |
| Outbox/Inbox  | `MassTransit.EntityFrameworkCore` 8.5.9                              |

`UseSnakeCaseNamingConvention()` sayesinde C# `FullName` → kolon `full_name`, `RolePermission` → tablo `role_permission` olur. EntityConfiguration'larda çoğu yerde `HasColumnName` açıkça yazılır; convention ise default davranıştır.

## Şemalar

İki PostgreSQL şeması kullanılır:

```csharp theme={null}
public const string DEFAULT_SCHEMA   = "public";    // business aggregate'leri
public const string MESSAGING_SCHEMA = "messaging"; // MassTransit outbox/inbox
```

`messaging` şeması, MassTransit'in EF Core Outbox/Inbox tablolarını (`inbox_state`, `outbox_state`, `outbox_message`) business tablolarından ayrı tutar. Böylece infrastructure messaging detayı `public` şemasını kirletmez.

<Info>
  Hangfire ayrı bir `hangfire` şeması kullanır ama bu, EFCore projesinin değil `Infrastructure.Jobs.Hangfire` projesinin sorumluluğundadır.
</Info>

## Klasör yapısı

```text theme={null}
DiyanetCleanArchitecture.Infrastructure.EFCore/
├── DiyanetCleanArchitectureDbContext.cs
├── DependencyInjection.cs                       # AddInfrastructureEFCore
├── MigrationService.cs                          # IHostedService — AutoDeploy migrate
├── DiyanetCleanArchitectureDesignTimeDbContextFactory.cs
├── DesignTimeDbContextFactoryBase.cs            # appsettings okur (dotnet ef için)
├── Interceptors/
│   └── AuditInterceptor.cs                      # audit + soft-delete
├── Repositories/
│   ├── EFRepository.cs                          # write — IRepository<T>
│   ├── EFCacheRepository.cs                     # read kaynağı (cache'siz)
│   ├── CachedRepository.cs                      # IReadRepository<T> decorator
│   ├── RolePermissionRepository.cs
│   └── UserContextRepository.cs
├── EntityConfigurations/                        # IEntityTypeConfiguration<T>
│   ├── UserConfigurations/
│   ├── RoleConfigurations/
│   ├── CitizenConfigurations/
│   └── ...                                      # her aggregate için bir klasör
├── Migrations/                                  # EF Core migration'lar + snapshot
└── SeedWork/
    ├── DevDataSeeder.cs                         # bootstrap admin (config-driven)
    ├── DistrictSeeder.cs                        # Districts.csv → 973 ilçe
    ├── MediatorExtension.cs                     # DispatchDomainEventsAsync
    ├── IAuditUserContext.cs                     # audit aktör kimliği
    └── MigrationOptions.cs                      # Services:Migration:AutoDeploy
```

## SaveChanges akışı

```mermaid theme={null}
flowchart LR
    UoW["UnitOfWork.SaveEntitiesAsync()"] --> SC["base.SaveChangesAsync()"]
    SC --> AI[AuditInterceptor<br/>CreatedBy / UpdatedBy / soft-delete]
    AI --> DB[(PostgreSQL)]
    SC --> DE["DispatchDomainEventsAsync()"]
    DE --> M[MediatR Publish → handler'lar]
    DE --> EB[IEventBus → MassTransit Outbox]
```

`AuditInterceptor` `SaveChanges` anında devreye girer; domain event dispatch ise `SaveEntitiesAsync` içinde `SaveChanges` **sonrası** çalışır. Detaylar ilgili sayfalarda.

## Bu bölümde

<CardGroup cols={2}>
  <Card title="DbContext & Repository" href="/data/dbcontext">
    DbSet'ler, OnModelCreating, value object map'leme, EFRepository / CachedRepository, UnitOfWork.
  </Card>

  <Card title="Migrations" href="/data/migrations">
    `dotnet ef` komutları, DesignTime factory, MigrationService AutoDeploy, migration listesi.
  </Card>

  <Card title="Audit Interceptor" href="/data/audit-interceptor">
    `AuditInterceptor`, `IAuditUserContext`, OnConfiguring'e eklenme nedeni.
  </Card>

  <Card title="Soft Delete" href="/data/soft-delete">
    `ISoftDeletable`, global query filter, restore, partial unique index.
  </Card>

  <Card title="Seed Data" href="/data/seed-data">
    `DevDataSeeder`, `DistrictSeeder`, `HasData`, prod davranışı.
  </Card>
</CardGroup>
