EFEF Core Handbook

REFERANS

Provider Uyumluluğu — SQL Server, PostgreSQL, Oracle, SQLite

EF Core'un Fluent API'sinin %90'ı provider-agnostic çalışır. Ancak bazı özellikler (Temporal Tables, JSON sütun syntax'ı, index tipleri) provider'a özgüdür.

Ortak (Tüm Provider'larda Çalışan) API

// Bunlar HER YERDE çalışır — SQL Server, PostgreSQL, SQLite, Oracle, MySQL...
builder.HasKey(p => p.Id);
builder.HasIndex(p => p.Email).IsUnique();
builder.Property(p => p.Name).IsRequired().HasMaxLength(200);
builder.HasOne(p => p.Category).WithMany(c => c.Products).HasForeignKey(p => p.CategoryId);
builder.OwnsOne(p => p.Address);
builder.HasQueryFilter(p => !p.IsDeleted);
builder.ToTable("Products");
builder.HasData(...);
builder.Ignore(p => p.Computed);

Provider-Specific Farklılıklar

PK Üretimi (Auto-Increment)

// Fluent API aynı — oluşan SQL farklı:
builder.Property(p => p.Id).ValueGeneratedOnAdd();
Provider SQL Çıktısı
SQL Server INT IDENTITY(1,1)
PostgreSQL INT GENERATED ALWAYS AS IDENTITY veya SERIAL
SQLite INTEGER PRIMARY KEY AUTOINCREMENT
Oracle NUMBER GENERATED ALWAYS AS IDENTITY
MySQL INT AUTO_INCREMENT

String / Unicode Davranışı

Provider IsUnicode(true) IsUnicode(false) Varsayılan
SQL Server NVARCHAR VARCHAR NVARCHAR
PostgreSQL TEXT (hep Unicode) TEXT (fark yok) TEXT
SQLite TEXT (hep Unicode) TEXT (fark yok) TEXT
Oracle NVARCHAR2 VARCHAR2 VARCHAR2
MySQL VARCHAR (charset'e bağlı) VARCHAR utf8mb4 ile

JSON Columns

// Fluent API aynı:
builder.OwnsOne(p => p.Metadata, m => m.ToJson());
Provider Destek SQL Tipi LINQ-to-JSON
SQL Server EF Core 7+ NVARCHAR(MAX) Full
PostgreSQL (Npgsql) EF Core 7+ jsonb Full + extra ops
SQLite
Oracle 21c+ kısıtlı JSON Kısıtlı
MySQL (Pomelo) 8.0+ JSON Temel

Temporal Tables

Provider Native Destek Alternatif
SQL Server IsTemporal()
PostgreSQL Trigger-based audit tablolar veya pgAudit eklentisi
SQLite Uygulama seviyesinde audit log
Oracle Flashback FLASHBACK TABLE (farklı API)

Sequences & HiLo

modelBuilder.HasSequence<int>("OrderNumbers").StartsAt(1000);
builder.Property(o => o.OrderNo).HasDefaultValueSql("NEXT VALUE FOR OrderNumbers");
Provider Sequence HiLo
SQL Server
PostgreSQL
SQLite
Oracle
MySQL

EF.Functions Farklılıkları

Fonksiyon SQL Server PostgreSQL (Npgsql) SQLite
Like LIKE LIKE / ILIKE LIKE
DateDiffDay DATEDIFF (kullan: date - date)
Contains (FTS) CONTAINS (kullan: EF.Functions.ToTsVector)
Random NEWID() random() random()
Collate
ILike (case-insensitive) (Npgsql özel)
JsonContains (Npgsql özel)

PostgreSQL Özel — Npgsql Provider

// NuGet: Npgsql.EntityFrameworkCore.PostgreSQL
builder.Services.AddDbContext<AppDbContext>(options =>
    options.UseNpgsql(connectionString));

// PostgreSQL'e özgü özellikler
builder.Property(p => p.Tags).HasColumnType("text[]");          // Native array
builder.Property(p => p.SearchVector).HasColumnType("tsvector"); // Full-text
builder.Property(p => p.Location).HasColumnType("point");        // Geometric
builder.HasIndex(p => p.Name).HasMethod("gin");                  // GIN index
builder.Property(p => p.Data).HasColumnType("jsonb");            // Binary JSON

// ILIKE (case-insensitive like — PostgreSQL'e özel)
var results = context.Products
    .Where(p => EF.Functions.ILike(p.Name, "%telefon%"))
    .ToListAsync();

Oracle Özel

// NuGet: Oracle.EntityFrameworkCore
builder.Services.AddDbContext<AppDbContext>(options =>
    options.UseOracle(connectionString));

// Oracle kısıtları
// - Tablo adı max 128 karakter (eski: 30)
// - NVARCHAR2 max 2000 byte
// - Boolean → NUMBER(1) olarak saklanır
builder.Property(p => p.Name).HasMaxLength(200); // NVARCHAR2(200)
builder.Property(p => p.IsActive);                // NUMBER(1)

MySQL Özel (Pomelo)

// NuGet: Pomelo.EntityFrameworkCore.MySql
builder.Services.AddDbContext<AppDbContext>(options =>
    options.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString)));

// MySQL'e özgü
builder.Property(p => p.Name).HasCharSet("utf8mb4");
builder.ToTable(t => t.HasCharSet("utf8mb4"));

Provider Seçimi Pratik Rehber

Senaryo Önerilen Provider Neden
Enterprise / Kurumsal SQL Server veya Oracle Temporal tables, row-level security, lisans desteği
Startup / SaaS PostgreSQL Ücretsiz, JSON native, array, FTS güçlü
Embedded / Mobil SQLite Dosya tabanlı, sıfır kurulum
Legacy sistem MySQL Yaygın hosting desteği
Çoklu DB desteği gerekli Fluent API + provider-agnostic kal EF.Functions yerine LINQ kullan

Altın kural: Eğer birden fazla provider desteklenecekse, provider-specific API'lerden (EF.Functions.DateDiff, IsTemporal, HasMethod) kaçınılmalı ve saf Fluent API + LINQ ile kalınmalı.