EFEF Core Handbook

REFERANS

Conventions Özetleri

EF Core, model oluşturulurken varsayılan kurallar (conventions) uygular: Id → PK, int → IDENTITY, navigation property → FK, DbSet adı → tablo adı.

EF Core Varsayılan Davranışları

Kural Açıklama Örnek
Id veya {TypeName}Id Otomatik PK Product.Id veya Product.ProductId
int, long PK IDENTITY (ValueGeneratedOnAdd) int IdIDENTITY(1,1)
Guid PK Client-side GUID üretimi Guid Id → newsequentialid() değil
Referans tipler (string hariç) Nullable Category? Category
string NOT NULL (EF Core 6+ nullable ref types) string Name → NOT NULL
int, bool, decimal vb. NOT NULL decimal Price → NOT NULL
int?, bool? vb. Nullable int? Stock → NULL
FK sütun adı {NavigationName}{PK} Category nav → CategoryId FK
İlişki cascade Required → Cascade, Optional → ClientSetNull Aşağıda detay
Index FK → otomatik index oluşmaz (convention yok!) Manuel eklemen gerek
Tablo adı DbSet property adı DbSet<Product> Products[Products]
Schema Varsayılan dbo (SQL Server) public (PostgreSQL)

İsimlendirme Conventions

Ne Convention Sonuç
Tablo adı DbSet<T> property adı Products, Categories
DbSet yoksa Class adı Product (tekil)
Join tablo (N-N) {Entity1}{Entity2} (alfabetik) ProductTag
Shadow FK {Navigation}{PK} CategoryId
Alternate Key Convention yok Manuel tanım gerek

FK & Cascade Delete Conventions

İlişki Tipi FK Nullable? Delete Behavior Sonuç
Required (1-N) Hayır (int) Cascade Parent silinince child'lar da silinir
Optional (1-N) Evet (int?) ClientSetNull Parent silinince FK = NULL
Required (1-1) Hayır Cascade Parent silinince dependent silinir
N-N (skip nav) Cascade Join tablosu kaydı silinir
// Cascade davranışı override etme
builder.HasOne(p => p.Category)
    .WithMany(c => c.Products)
    .OnDelete(DeleteBehavior.Restrict);  // FK varken parent silinemez

// Tüm ilişkilerde cascade'i kapatma (global)
foreach (var fk in modelBuilder.Model.GetEntityTypes()
    .SelectMany(t => t.GetForeignKeys())
    .Where(fk => !fk.IsOwnership && fk.DeleteBehavior == DeleteBehavior.Cascade))
{
    fk.DeleteBehavior = DeleteBehavior.Restrict;
}

Tip Mapping Conventions

C# Tipi SQL Server PostgreSQL SQLite
string nvarchar(max) text TEXT
int int integer INTEGER
long bigint bigint INTEGER
decimal decimal(18,2) numeric TEXT
bool bit boolean INTEGER
DateTime datetime2 timestamp with time zone TEXT
Guid uniqueidentifier uuid TEXT
byte[] varbinary(max) bytea BLOB
enum int (varsayılan) integer INTEGER

Convention Özelleştirme (EF Core 7+)

// Tüm string property'leri varsayılan olarak 200 karakter yap
protected override void ConfigureConventions(ModelConfigurationBuilder config)
{
    config.Properties<string>().HaveMaxLength(200);
    config.Properties<decimal>().HavePrecision(18, 2);

    // Enum'ları her yerde string olarak sakla
    config.Properties<Enum>().HaveConversion<string>();

    // DateOnly / TimeOnly desteği (SQL Server)
    config.Properties<DateOnly>().HaveColumnType("date");
    config.Properties<TimeOnly>().HaveColumnType("time");
}

Convention Öncelik Sırası (Düşükten Yükseğe)

1. EF Core Built-in Conventions (en düşük)
2. ConfigureConventions() — global type config
3. Custom IConvention implementations (bkz. Bölüm 42)
4. Data Annotations
5. Fluent API (OnModelCreating) — EN YÜKSEK

Üst seviye her zaman alt seviyeyi ezer. [MaxLength(100)] annotation'ı, ConfigureConventions'daki HaveMaxLength(200) kuralını override eder. Fluent API ise hepsini ezer.