Episode ini membuka akses database dengan Entity Framework Core: DbContext, entity mapping, migrations, querying dengan LINQ dan raw SQL, serta perbandingan provider SQL Server, PostgreSQL, dan SQLite. Kalian siap membangun lapisan persistence yang solid.

Aplikasi nyata membutuhkan penyimpanan. Episode 9 membahas Entity Framework Core (EF Core) — ORM bawaan .NET yang menjadi cara utama mengakses database relasional. Dengan EF Core, kalian bekerja dengan objek C# alih-alih menulis SQL berulang kali, sambil tetap bisa turun ke SQL mentah saat dibutuhkan.
Di episode ini kalian akan mengonfigurasi DbContext, membuat dan menjalankan migrations, melakukan query dengan LINQ, serta memahami perbedaan provider database. Hasilnya adalah fondasi data yang akan dipakai web API di fase 4.
EF Core ditambahkan sebagai paket NuGet. Pilih provider sesuai database kalian:
dotnet add package Microsoft.EntityFrameworkCore.Sqlitedotnet add package Microsoft.EntityFrameworkCore.Sqlite menambahkan provider SQLite beserta dependensi inti EF Core. Untuk SQL Server gunakan Microsoft.EntityFrameworkCore.SqlServer, untuk PostgreSQL gunakan Microsoft.EntityFrameworkCore.Npgsql.
Tool CLI dibutuhkan untuk membuat migrations:
dotnet tool install --global dotnet-efdotnet tool install --global dotnet-ef memasang tool dotnet-ef yang menyediakan perintah dotnet ef. Pastikan ini terpasang sebelum melanjutkan ke bagian migrations.
DbContext mewakili sesi kerja dengan database — tempat entitas dipetakan:
public class Produk
{
public int Id { get; set; }
public string Nama { get; set; }
public decimal Harga { get; set; }
}
public class AppDbContext : DbContext
{
public DbSet<Produk> Produk { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder options)
=> options.UseSqlite("Data Source=app.db");
}DbSet<Produk> memaparkan tabel Produk sebagai koleksi yang bisa di-query. Konvensi EF Core menebak nama tabel dan kolom dari nama properti; kustomisasi mapping ditulis di method OnModelCreating.
Migrations menjaga skema database sinkron dengan model:
dotnet ef migrations add InitialCreate
dotnet ef database updatedotnet ef migrations add InitialCreate membuat file migration berisi perubahan skema, dan dotnet ef database update menerapkannya ke database. Migration adalah file C# yang masuk Git — jadi perubahan skema bisa direview dalam code review.
Query ditulis dengan LINQ yang type-safe dan terkompilasi:
using var db = new AppDbContext();
var murah = await db.Produk
.Where(p => p.Harga < 1_000_000m)
.OrderByDescending(p => p.Harga)
.ToListAsync();
foreach (var p in murah)
{
Console.WriteLine($"{p.Nama} - {p.Harga}");
}db.Produk.Where(p => p.Harga < 1_000_000m) diterjemahkan menjadi SQL oleh EF Core. ToListAsync mengeksekusi query secara asinkron. LINQ memeriksa tipe saat kompilasi — kolom yang salah akan menghasilkan error compile, bukan runtime.
Untuk query yang sulit diekspresikan dengan LINQ, EF Core menyediakan FromSqlRaw:
var hasil = await db.Produk
.FromSqlRaw("SELECT * FROM Produk WHERE Harga > {0}", 500_000m)
.ToListAsync();FromSqlRaw mengeksekusi SQL mentah dan memetakan hasil ke entitas. Gunakan parameterization (placeholder {0}) untuk mencegah SQL injection — jangan pernah menggabungkan nilai ke string SQL secara manual.
EF Core memakai provider untuk menerjemahkan LINQ ke dialek SQL masing-masing database:
UseSqlServer, fitur lengkap, umum di enterprise.UseNpgsql, open-source, dukungan JSONB dan full-text.UseSqlite, file-based, ideal untuk dev dan prototipe.dotnet add package Microsoft.EntityFrameworkCore.NpgsqlMengganti provider cukup dengan menambahkan paket dan mengubah method konfigurasi di OnConfiguring. Perbedaan sintaks SQL ditangani EF Core, sehingga kode query kalian tetap sama.
Connection string sebaiknya berada di konfigurasi, bukan hardcode di kode. Pindahkan dari OnConfiguring dengan membaca IConfiguration:
var koneksi = builder.Configuration.GetConnectionString("Default");
builder.Services.AddDbContext<AppDbContext>(options =>
options.UseSqlite(koneksi));AddDbContext meregistrasikan DbContext dengan lifetime scoped — pasangan sempurna dengan DI episode 8. Nilai Default bisa diambil dari appsettings.json atau environment variable ConnectionStrings__Default.
Info
Pada production, jangan jalankan database update langsung dari pipeline. Gunakan migration yang dijalankan sebagai langkah eksplisit dengan backup, atau migrasi saat startup di environment pengembangan saja.
Inti yang harus dibawa pulang:
Di episode 10 selanjutnya kita akan membahas configuration dan application settings — options pattern dan binding ke POCO, multi-environment settings, secrets management, configuration providers JSON, env vars, dan command line, serta strongly typed configuration dan validation.