Entity Framework Core: DbContext și DbSet în C# (.NET)

Ecosistem .NET: DI, EF Core și teste EF Core 1.0 (exemple: EF Core 10)

DbContext este legătura cu baza de date în EF Core: DbSet<T> reprezintă un tabel, iar SaveChanges salvează adăugările, modificările și ștergerile.

Sintaxă C#
class MagazinContext : DbContext { public DbSet<Produs> Produse => Set<Produs>(); }   db.SaveChanges();

Ce face Entity Framework Core: DbContext și DbSet

Entity Framework Core este ORM-ul oficial .NET: lucrezi cu clase C#, iar EF generează SQL pentru SQL Server, PostgreSQL, SQLite, MySQL și altele, prin pachete numite provideri (de exemplu Microsoft.EntityFrameworkCore.Sqlite). Clasa ta derivată din DbContext conține câte un DbSet<T> pentru fiecare tabel.

Contextul urmărește obiectele încărcate (change tracking): Add, Remove sau simpla modificare a unei proprietăți sunt ținute în memorie, iar SaveChanges() le trimite pe toate într-o tranzacție și întoarce numărul de rânduri afectate. O proprietate Id sau <Tip>Id devine automat cheie primară.

Un DbContext este gândit pentru o unitate de lucru scurtă (o cerere HTTP) și nu este sigur pentru mai multe fire de execuție. În ASP.NET Core îl înregistrezi cu AddDbContext, iar conexiunea vine din configurare, nu din cod.

Exemple

Exemplul 1: Adăugare, modificare și ștergere cu SQLite

Pachet necesar: dotnet package add Microsoft.EntityFrameworkCore.Sqlite. EnsureDeleted/EnsureCreated refac baza la fiecare rulare, doar pentru demonstrație; în proiecte reale se folosesc migrări.

using Microsoft.EntityFrameworkCore;

using var db = new MagazinContext();
db.Database.EnsureDeleted();
db.Database.EnsureCreated();

db.Produse.AddRange(
    new Produs { Nume = "Laptop", Pret = 3500 },
    new Produs { Nume = "Mouse", Pret = 80 });
Console.WriteLine($"Salvate: {db.SaveChanges()}");

var mouse = db.Produse.Single(p => p.Nume == "Mouse");
mouse.Pret = 70;
db.SaveChanges();

db.Produse.Remove(db.Produse.Single(p => p.Nume == "Laptop"));
db.SaveChanges();

foreach (var p in db.Produse)
    Console.WriteLine($"{p.Id}: {p.Nume} - {p.Pret} lei");

public class Produs
{
    public int Id { get; set; }
    public string Nume { get; set; } = "";
    public int Pret { get; set; }
}

public class MagazinContext : DbContext
{
    public DbSet<Produs> Produse => Set<Produs>();

    protected override void OnConfiguring(DbContextOptionsBuilder options) =>
        options.UseSqlite("Data Source=magazin.db");
}

Rezultat

Salvate: 2
2: Mouse - 70 lei

Exemplul 2: Înregistrare în ASP.NET Core și configurarea modelului

Contextul primește opțiunile prin constructor, iar șirul de conexiune vine din appsettings.json. OnModelCreating stabilește lungimi, indexuri și numele tabelelor. Codul nu afișează nimic; pornește aplicația web.

// Program.cs
using Microsoft.EntityFrameworkCore;

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<MagazinContext>(options =>
    options.UseSqlite(builder.Configuration.GetConnectionString("Magazin")));

var app = builder.Build();
app.MapGet("/produse", async (MagazinContext db) => await db.Produse.ToListAsync());
app.Run();

public class MagazinContext(DbContextOptions<MagazinContext> options) : DbContext(options)
{
    public DbSet<Produs> Produse => Set<Produs>();

    protected override void OnModelCreating(ModelBuilder model)
    {
        model.Entity<Produs>(p =>
        {
            p.ToTable("Produse");
            p.Property(x => x.Nume).HasMaxLength(200).IsRequired();
            p.HasIndex(x => x.Nume).IsUnique();
        });
    }
}

public class Produs
{
    public int Id { get; set; }
    public string Nume { get; set; } = "";
    public int Pret { get; set; }
}

Greșeli frecvente

  • Un singur DbContext păstrat static și folosit în toată aplicația: urmărește tot mai multe obiecte, consumă memorie și aruncă excepții când e folosit din mai multe fire.
  • Modificări fără SaveChanges(): nimic nu ajunge în baza de date.
  • EnsureCreated() într-un proiect care folosește migrări: creează schema fără tabelul de istoric al migrărilor, iar dotnet ef database update eșuează apoi.

Comenzi înrudite