Webframeworkk/ASP.NET Core/Entity Framework Core

Dieses Tutorial bietet einen umfassenden Überblick über Entity Framework Core (EF Core), das moderne, leichtgewichtige und plattformübergreifende Object-Relational Mapper (ORM) Framework für .NET.


1. Einführung in EF Core

EF Core vereinfacht die Interaktion mit Datenbanken, indem es Ihnen ermöglicht, mit Daten als .NET-Objekte (Entities) zu arbeiten, anstatt rohe SQL-Abfragen zu schreiben.

Vorteile:

  • Produktivität: Weniger Boilerplate-Code für Datenbankoperationen.
  • Objektorientiert: Nutzung vertrauter C#-Konzepte.
  • Typsicherheit: LINQ-Abfragen werden zur Kompilierzeit geprüft.
  • Plattformübergreifend: Unterstützt SQL Server, SQLite, PostgreSQL, MySQL usw.

Nachteile:

  • Abstraktions-Overhead: Kann bei komplexen Abfragen weniger effizient sein als handgeschriebenes SQL.
  • Lernkurve: Erfordert Verständnis der internen Funktionsweise für optimale Performance.

2. Die Architektur: Ein Drei-Schichten-Modell

  1. Konzeptionelles Modell (Entity Model): Ihre C#-Klassen, die das Datenbankschema repräsentieren.
  2. Mapping: Die Brücke zwischen Ihren Klassen und der Datenbank (konfiguriert über Data Annotations oder Fluent API).
  3. Speichermodell (Database Schema): Die tatsächliche Struktur in der Datenbank (Tabellen, Spalten, Constraints).

3. DbContext und DbSet

Der DbContext ist das Herzstück von EF Core. Er fungiert als Sitzung mit der Datenbank.

Hauptaufgaben:

  • Verbindungsmanagement.
  • Änderungsverfolgung (Change Tracking).
  • Übersetzung von LINQ in SQL.

Beispiel: PersonsDbContext

public class PersonsDbContext : DbContext
{
    public PersonsDbContext(DbContextOptions options) : base(options) { }

    public DbSet<Country> Countries { get; set; }
    public DbSet<Person> Persons { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
        modelBuilder.Entity<Country>().ToTable("Countries");
        modelBuilder.Entity<Person>().ToTable("Persons");
    }
}

4. Connection Strings

Connection Strings definieren, wo sich Ihre Datenbank befindet und wie darauf zugegriffen wird.

Empfohlener Speicherort: appsettings.json

{
  "ConnectionStrings": {
    "DefaultConnection": "Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=PersonsDatabase;Integrated Security=True;"
  }
}

Registrierung in Program.cs:

builder.Services.AddDbContext<PersonsDbContext>(options => {
    options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection"));
});

5. Entwicklungsansätze

  • Code-First: Sie schreiben C#-Klassen, EF Core erstellt die Datenbank. Ideal für neue Projekte.
  • Database-First: Sie starten mit einer bestehenden Datenbank, EF Core generiert die Klassen. Ideal für Legacy-Systeme.

6. Migrationen und Seed-Daten

Migrationen ermöglichen es, Schemaänderungen versioniert zu verwalten.

Wichtige Befehle (Package Manager Console):

  • Add-Migration InitialCreate: Erstellt ein Skript für die aktuellen Modelländerungen.
  • Update-Database: Wendet die Migrationen auf die Datenbank an.

Seed-Daten (Initialdaten): Nutzen Sie HasData in OnModelCreating, um Tabellen vorab zu befüllen (z. B. Länderlisten).

modelBuilder.Entity<Country>().HasData(
    new Country() { CountryID = Guid.NewGuid(), CountryName = "Deutschland" }
);

7. Fluent API vs. Data Annotations

Während Data Annotations ([Key], [Required]) einfach sind, bietet die Fluent API mehr Flexibilität direkt im DbContext.

Beispiel Fluent API:

modelBuilder.Entity<Person>()
    .Property(p => p.TIN)
    .HasColumnName("TaxIdentificationNumber")
    .HasColumnType("varchar(8)")
    .IsRequired();

8. CRUD-Operationen im Controller

Dank EF Core lassen sich Datenbankzugriffe schlank im Service-Layer implementieren.

Beispiel: Person hinzufügen (Create)

public async Task<PersonResponse> AddPerson(PersonAddRequest personRequest)
{
    Person person = personRequest.ToPerson();
    person.PersonID = Guid.NewGuid();
    
    _db.Persons.Add(person);
    await _db.SaveChangesAsync();
    
    return person.ToPersonResponse();
}

Eager Loading mit Include(): Um verwandte Daten (z. B. das Land einer Person) sofort mitzuladen:

var persons = await _db.Persons.Include(p => p.Country).ToListAsync();

9. Fortgeschrittene Funktionen

Stored Procedures EF Core erlaubt die Ausführung von Stored Procedures über FromSqlRaw (für Abfragen) oder ExecuteSqlRaw (für Befehle).

var persons = _db.Persons.FromSqlRaw("EXECUTE [dbo].[GetAllPersons]").ToList();

Berichterstellung (PDF & CSV)

  • PDF: Mit Bibliotheken wie Rotativa können Razor-Views direkt als PDF gerendert werden (return new ViewAsPdf(...)).
  • CSV: Mit CsvHelper können Daten effizient in Streams geschrieben werden.

10. Best Practices & Tipps

  1. Asynchrone Programmierung: Nutzen Sie immer ToListAsync(), SaveChangesAsync() etc., um die Skalierbarkeit zu erhöhen.
  2. Thin Controllers: Lagern Sie die EF-Logik in separate Service-Klassen aus.
  3. DTOs nutzen: Verwenden Sie Request- und Response-Modelle, um Ihre Datenbank-Entities vor der UI zu verbergen.
  4. Referenzielle Integrität: Achten Sie auf Primär- und Fremdschlüssel-Konfigurationen, um Datenkonsistenz zu wahren.

Tutorial erstellt für Thorsten - Viel Erfolg bei der Entwicklung mit ASP.NET Core MVC!


Kategorien: Keine
Zuletzt aktualisiert am 26.02.2026 04:37