
Performance-Probleme in .NET Webanwendungen entstehen häufig durch ineffiziente Datenbankabfragen und unnötig große Datenmengen.
Der Artikel zeigt, wie sich mit Entity Framework, Pagination (Skip / Take), AsNoTracking() und gezielter Projektion (Select) performante und skalierbare Datenabfragen umsetzen lassen.
Weniger Datenübertragung, effizientere Queries und bessere Skalierbarkeit sorgen für schnellere Anwendungen und geringere Serverlast.
Die Performance-Optimierung spielt in modernen .NET Webanwendungen eine zentrale Rolle.
Werden große Datenmengen verarbeitet, können langsame Datenbankabfragen die gesamte Anwendung negativ beeinflussen. Häufig werden zu viele Daten geladen oder nicht effizient verarbeitet.
Dieser Artikel zeigt praxisnahe Techniken zur Verbesserung der Performance in .NET Webanwendungen und erläutert, wie optimierte Datenabfragen die Skalierbarkeit und Effizienz erhöhen.
Ein häufiges Problem besteht darin, dass sämtliche Daten aus der Datenbank geladen und anschließend erst im Anwendungscode gefiltert werden.
Dieses Vorgehen führt zu:
Insbesondere bei großen Datenbanken und umfangreichen Tabellen kann dies die Performance moderner .NET Webanwendungen erheblich beeinträchtigen.
Eine bewährte Methode zur Performance-Optimierung besteht darin, die Verarbeitung direkt in der Datenbank durchzuführen. Filterung, Sortierung und Datenauswahl sollten bereits innerhalb der Datenabfrage definiert werden.
Zusätzlich empfiehlt es sich, ausschließlich die tatsächlich benötigten Daten zu laden. Durch den Einsatz von Pagination und gezielter Datenprojektion lässt sich die Datenmenge deutlich reduzieren.
Die folgende Implementierung zeigt eine optimierte Datenabfrage mit Pagination in einer modernen .NET Webanwendung.
1public class PagedResult<T>
2
3{
4 public List<T> Items { get; set; }
5 public int TotalCount { get; set; }
6 public int Page { get; set; }
7 public int PageSize { get; set; }
8}
9
10public class CustomerDto
11{
12 public int Id { get; set; }
13 public string Name { get; set; }
14}
15
16public class CustomerService
17
18{
19 private readonly AppDbContext _context;
20 public CustomerService(AppDbContext context)
21
22 {
23 _context = context;
24 }
25 public async Task<PagedResult<CustomerDto>> GetCustomersAsync(string status, int page, int pageSize)
26
27 {
28 var query = _context.Customers
29 .AsNoTracking()
30 .Where(x => x.Status == status);
31
32 var totalCount = await query.CountAsync();
33 var items = await query
34 .OrderBy(x => x.Id)
35 .Skip((page - 1) * pageSize)
36 .Take(pageSize)
37 .Select(x => new CustomerDto
38 {
39 Id = x.Id,
40 Name = x.Name
41 })
42 .ToListAsync();
43
44 return new PagedResult<CustomerDto>
45 {
46 Items = items,
47 TotalCount = totalCount,
48 Page = page,
49 PageSize = pageSize
50 };
51 }
52}
1app.MapGet("/customers", async (CustomerService service, string status, int page = 1, int pageSize = 50) =>
2
3{
4 var result = await service.GetCustomersAsync(status, page, pageSize);
5 return Results.Ok(result);
6
7});
In diesem Beispiel wird eine vollständige Pagination implementiert. Die Basisabfrage wird einmal definiert und anschließend für mehrere Operationen wiederverwendet.
Mit CountAsync() wird zunächst die Gesamtanzahl der Datensätze berechnet. Anschließend werden mithilfe von Skip() und Take() nur die tatsächlich benötigten Daten geladen.
Durch die Verwendung von Select() werden ausschließlich relevante Felder übertragen. Dadurch reduziert sich die Datenmenge erheblich, was die Performance der .NET Webanwendung verbessert.
AsNoTracking() sorgt zusätzlich für eine höhere Effizienz, da Entity Framework keine Änderungsverfolgung für die geladenen Datensätze durchführen muss.
Zu beachten ist, dass CountAsync() bei sehr großen Tabellen einen vollständigen Scan auslösen kann und damit unter Umständen teurer ist als die eigentliche Datenabfrage. In performance-kritischen Szenarien sollte das Count entweder gecached oder ganz weggelassen werden, etwa bei "Infinite Scroll"-Patterns statt klassischer "Seite X von Y"-Anzeige.
Das Ergebnis wird abschließend in einem PagedResult-Objekt zurückgegeben, das sowohl die eigentlichen Daten als auch Metainformationen zur Pagination enthält. Dieses Muster wird häufig in skalierbaren und professionellen Webanwendungen eingesetzt.
Durch optimierte Datenabfragen, Pagination und gezielte Datenprojektion lässt sich die Performance moderner .NET Webanwendungen deutlich verbessern.
Entscheidend ist, nur die benötigten Daten zu laden und möglichst viele Verarbeitungsschritte direkt in die Datenbank zu verlagern.
Bei sehr großen Datenmengen stößt klassische Offset-Pagination mit Skip() und Take() allerdings selbst an Grenzen, da die Datenbank auch übersprungene Zeilen verarbeiten muss. In solchen Fällen ist Keyset-Pagination (Filterung über die letzte ID statt Skip) die performantere Alternative.
Diese Best Practices helfen dabei, performante, skalierbare und wartbare Anwendungen zu entwickeln.

Unser Geschäftsführer Tibor Csizmadia und unser Kundenbetreuer Jens Walter stehen Ihnen persönlich zur Verfügung. Profitieren Sie von unserer langjährigen Erfahrung und erhalten Sie eine kompetente Beratung in einem unverbindlichen Austausch.