Architekturentscheidungen mit EF Core Architektur

Thomas R.
12/2025

Architekturentscheidungen mit EF Core – vom Domain Model bis zur performanten Datenbank

Softwarearchitektur entscheidet maßgeblich über die Zukunftsfähigkeit einer Anwendung. Besonders in datengetriebenen Systemen ist der Umgang mit Persistenzschichten zentral – hier kommt Entity Framework Core (EF Core) ins Spiel. Als leistungsstarkes ORM erleichtert es den Datenzugriff in .NET-Anwendungen erheblich, birgt aber auch architektonische Herausforderungen.

Zwischen sauberem Domain Design, performanter Datenbankabfrage und wartbarem Code müssen Entwickler oft schwierige Entscheidungen treffen. Eine unüberlegte Modellierung kann schnell zu Problemen führen: unerwartete Ladezeiten, unübersichtliche Entitäten oder schwer nachvollziehbare Abhängigkeiten.

Studien und Projekterfahrungen zeigen, dass gut strukturierte EF-Core-Architekturen die Wartungskosten um bis zu 30 % reduzieren können. Klare Trennung von Domänenschicht, Infrastruktur und Datenzugriff sorgt nicht nur für bessere Performance, sondern auch für Stabilität und Erweiterbarkeit im gesamten Lebenszyklus einer Anwendung.

Das Problem: Fehlende Architektur im Datenzugriff

In vielen Projekten wird EF Core rein technisch genutzt – als bequeme Möglichkeit, Daten zu speichern und zu laden. Doch ohne klare Architekturprinzipien entsteht schnell ein „Data Access Chaos“:

  • Fat Repositories, die Geschäftslogik und Datenzugriff vermischen
  • N+1-Queries durch unkontrolliertes Lazy Loading
  • Eng gekuppelte Entitäten, die Änderungen in der Datenbank direkt ins Domain Model durchschlagen
  • Fehlende Trennung von Commands und Queries, was zu ineffizienter Datenverarbeitung führt

Das Ergebnis: Systeme werden schwer wartbar, Änderungen riskant und Performance-Optimierungen mühsam.

Architekturentscheidungen mit EF Core – der Schlüssel zur Balance

Der bewusste Einsatz von Architekturmustern wie Domain-Driven Design (DDD), CQRS und Clean Architecture schafft klare Grenzen zwischen Domäne, Anwendung und Infrastruktur. EF Core wird dabei nicht zum zentralen Treiber des Designs, sondern zu einem austauschbaren Detail der Infrastruktur.

So bleibt das Domain Model frei von technischen Abhängigkeiten, die Datenbank performant angebunden und die Anwendung langfristig wartbar – eine solide Basis für nachhaltige Softwareentwicklung im .NET-Umfeld.

Vorteile:

  • Klare Trennung von Domäne, Anwendung und Datenzugriff
  • Höhere Wartbarkeit und geringere Komplexität
  • Bessere Testbarkeit durch entkoppelte Architektur

Praxisbeispiel: Saubere Architektur mit EF Core

Wir modellieren eine einfache „Task Management“-Domäne (Aufgabenverwaltung), die klar zwischen Domain, Application und Infrastructure trennt.

1// Domain/Entities/TaskItem.cs 
2
3namespace TaskManager.Domain.Entities 
4
5{ 
6    public class TaskItem 
7    { 
8        public Guid Id { get; private set; } = Guid.NewGuid(); 
9        public string Title { get; private set; } 
10        public bool IsCompleted { get; private set; } 
11        public TaskItem(string title) 
12
13        { 
14            Title = title; 
15        } 
16        public void Complete() => IsCompleted = true; 
17    } 
18}

1// Application/Interfaces/ITaskRepository.cs 
2
3namespace TaskManager.Application.Interfaces 
4{ 
5    using TaskManager.Domain.Entities; 
6    public interface ITaskRepository 
7    { 
8        Task<IEnumerable<TaskItem>> GetAllAsync(); 
9        Task AddAsync(TaskItem task); 
10        Task SaveChangesAsync(); 
11    } 
12}

1// Infrastructure/Data/AppDbContext.cs 
2
3using Microsoft.EntityFrameworkCore; 
4using TaskManager.Domain.Entities; 
5namespace TaskManager.Infrastructure.Data 
6
7{ 
8    public class AppDbContext : DbContext 
9    { 
10        public DbSet<TaskItem> Tasks { get; set; }  
11        public AppDbContext(DbContextOptions<AppDbContext> options) 
12            : base(options) { } 
13        protected override void OnModelCreating(ModelBuilder modelBuilder) 
14
15        { 
16            modelBuilder.Entity<TaskItem>().ToTable("Tasks"); 
17            base.OnModelCreating(modelBuilder); 
18        } 
19    } 
20} 

1// Infrastructure/Repositories/TaskRepository.cs 
2
3using Microsoft.EntityFrameworkCore; 
4using TaskManager.Application.Interfaces; 
5using TaskManager.Domain.Entities; 
6using TaskManager.Infrastructure.Data; 
7  
8
9namespace TaskManager.Infrastructure.Repositories 
10
11{ 
12    public class TaskRepository : ITaskRepository 
13
14    { 
15        private readonly AppDbContext _context; 
16        public TaskRepository(AppDbContext context) 
17        
18        { 
19            _context = context; 
20        } 
21
22        public async Task<IEnumerable<TaskItem>> GetAllAsync() => 
23            await _context.Tasks.AsNoTracking().ToListAsync(); 
24        public async Task AddAsync(TaskItem task) => 
25            await _context.Tasks.AddAsync(task); 
26        public async Task SaveChangesAsync() => 
27            await _context.SaveChangesAsync(); 
28    } 
29} 

1// WebAPI/Controllers/TasksController.cs 
2
3using Microsoft.AspNetCore.Mvc; 
4using TaskManager.Application.Interfaces; 
5using TaskManager.Domain.Entities; 
6namespace TaskManager.WebAPI.Controllers 
7
8{ 
9    [ApiController] 
10    [Route("api/[controller]")] 
11    public class TasksController : ControllerBase 
12
13    { 
14        private readonly ITaskRepository _repository; 
15        public TasksController(ITaskRepository repository) 
16
17        { 
18            _repository = repository; 
19        } 
20
21
22        [HttpGet] 
23
24        public async Task<IActionResult> GetAll() 
25
26        { 
27            var tasks = await _repository.GetAllAsync(); 
28            return Ok(tasks); 
29        } 
30
31  
32
33        [HttpPost] 
34
35        public async Task<IActionResult> Create([FromBody] string title) 
36
37        { 
38            var task = new TaskItem(title); 
39            await _repository.AddAsync(task); 
40            await _repository.SaveChangesAsync(); 
41            return CreatedAtAction(nameof(GetAll), new { id = task.Id }, task); 
42        } 
43    } 
44} 

Abschlusssatz zum Praxisbeispiel

Dieses Beispiel zeigt, wie EF Core sinnvoll in eine saubere Softwarearchitektur integriert werden kann, ohne die Domäne durch technische Details zu beeinträchtigen. Durch die klare Trennung von Domäne, Anwendung und Infrastruktur entsteht eine Struktur, die sowohl wartbar als auch flexibel bleibt. Neue Anforderungen können umgesetzt werden, ohne bestehende Logik zu verändern, und der Datenzugriff lässt sich bei Bedarf problemlos austauschen oder optimieren.

So verbindet eine wohldurchdachte EF-Core-Architektur klare fachliche Modelle mit effizienter Datenpersistenz – ein Ansatz, der langfristig Qualität, Performance und Erweiterbarkeit in modernen .NET-Anwendungen sicherstellt.

Typische Stolpersteine mit EF Core

  • Business-Logik im DbContext
    → Fachlogik (z. B. Validierungen, Berechnungen) wird fälschlicherweise in den Datenzugriff geschoben.
  • Anemisches Domain Model
    → Entitäten enthalten nur Daten, aber keine Fachregeln – Logik verteilt sich unstrukturiert über Services.
  • N+1-Query-Problem
    → Fehlendes Include() oder falsches Lazy Loading führt zu vielen kleinen Datenbankabfragen statt einer effizienten.

Fazit

Eine durchdachte Architektur mit EF Core legt das Fundament für nachhaltige und performante Anwendungen.

Durch die klare Trennung von Domäne, Anwendung und Infrastruktur bleibt der Code verständlich, testbar und flexibel gegenüber neuen Anforderungen oder Technologien.

Gerade in wachsenden Projekten zahlt sich dieser Ansatz aus:

  • geringerer Wartungsaufwand
  • bessere Testbarkeit
  • optimierte Performance
  • zukunftssichere Erweiterbarkeit

Statt datengetriebene Logik direkt in den Code zu mischen, entsteht mit EF Core und sauberer Architektur eine klare, stabile Struktur, die langfristig Qualität und Effizienz im gesamten .NET-Projekt sichert.

No items found.
Foto von Thomas
Thomas R.

Mehr zum Thema

Pfeil nach rechts (Verlinkung)
EF Core: Owned & Complex Types für saubere Datenmodellierung
05/2024

Entity Framework Owned Types | ComplexType C# Tutorial

Blauer Pfeil nach rechts (Verlinkung)
Entity Framework CRUD: Datenbankoperationen in .NET effizient umsetzen
06/2020

Entity Framework Tutorial | .NET CRUD Operationen Guide

Blauer Pfeil nach rechts (Verlinkung)
No items found.
No items found.

Lassen Sie uns gemeinsam wachsen.

Devware GmbH verpflichtet sich, Ihre Privatsphäre zu schützen. Wir benötigen Ihre Kontaktinformationen, um Sie bezüglich unserer Produkte und Dienstleistungen zu kontaktieren. Mit Klick auf Absenden geben Sie sich damit einverstanden. Weitere Informationen finden Sie unter Datenschutz. Ihre Daten behandeln wir vertraulich. Versprochen.
Vielen Dank für Ihr Vertrauen.
Unser Team prüft Ihre Anfrage sorgfältig und meldet sich in der Regel innerhalb von 48 Stunden bei Ihnen zurück.
Falls es besonders eilig ist, erreichen Sie uns auch telefonisch:
+ 49 (0) 202 478 269 0.
Da ist etwas schief gegangen beim Absenden des Formulars.