
Die Wahl der richtigen Datenzugriffstechnologie ist entscheidend für Performance, Wartbarkeit und Entwicklungsgeschwindigkeit von .NET‑Anwendungen. ADO.NET und Entity Framework Core (EF Core) repräsentieren dabei zwei grundlegend unterschiedliche Ansätze: ADO.NET bietet direkten, Low‑Level‑Datenbankzugriff mit maximaler Kontrolle, während EF Core als modernes ORM (Object‑Relational Mapping) die Komplexität von Datenbankoperationen abstrahiert.Dieser Artikel betrachtet beide Technologien, vergleicht ihre Stärken und Schwächen anhand konkreter Praxisbeispiele und unterstützt bei der Auswahl der passenden Lösung für zukünftige Projekte.
ADO.NET ist die fundamentale Datenzugriffstechnologie in .NET, die seit den Anfängen des Frameworks genutzt wird. Sie bietet direkten Zugriff auf Datenbankressourcen über Klassen wie SqlConnection, SqlCommand, SqlDataReader und SqlDataAdapter. Entwickler schreiben SQL‑Queries manuell und haben vollständige Kontrolle über jeden Aspekt der Datenbankinteraktion.
Vorteile:
Nachteile:
Entity Framework Core ist ein leichtgewichtiges, erweiterbares und plattformübergreifendes Open‑Source‑ORM‑Framework der beliebten Entity Framework‑Technologie. EF Core ermöglicht es Entwicklern, mit Datenbanken über stark typisierte C#‑Objekte zu arbeiten, ohne SQL‑Code schreiben zu müssen. Es generiert automatisch SQL‑Queries aus LINQ‑Ausdrücken, verwaltet Beziehungen zwischen Entitäten und bietet Funktionen wie Change Tracking, Migrationen und automatische Schemaerstellung.
Vorteile:
Nachteile:
Um Performance‑Unterschiede objektiv zu messen, wurden Benchmarks mit BenchmarkDotNet v0.14.0 auf .NET 9 durchgeführt.
Testumgebung:
Datenmodell:
1[Table("DataModels")]
2 public class DataModel
3 {
4 [Key]
5 [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
6 public int Id { get; set; }
7
8 [Required]
9 [MaxLength(100)]
10 public required string Name { get; set; }
11
12 public int Quantity { get; set; }
13 }
14
15DbContext-Konfiguration:
16 public class BenchmarkDbContext : DbContext
17 {
18 private const string ConnectionString =
19"Server=.;Database=BenchmarkDB;Integrated Security=true;TrustServerCertificate=true;";
20
21 public DbSet<DataModel> DataModels { get; set; }
22
23 protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
24 {
25 optionsBuilder.UseSqlServer(ConnectionString);
26 optionsBuilder.EnableSensitiveDataLogging(false);
27 optionsBuilder.LogTo(message => { }, Microsoft.Extensions.Logging.LogLevel.None);
28 }
29 }Das Logging wurde bewusst deaktiviert, um den EF Core-Overhead nichtkünstlich zu erhöhen. Getestet wurden vier Operationen mit jeweils 100, 1.000,10.000 Datensätzen.
Die ReadAll-Operation liest alle Datensätze aus derDatenbank und materialisiert sie als Liste.
EFCore-Implementierung (mit AsNoTracking):
1[Benchmark(Baseline = true)]
2public List<DataModel> EFCore_ReadAll_NoTracking()
3{
4 return _dbContext.DataModels.AsNoTracking().ToList();
5}
6ADO.NET Implementierung:
7[Benchmark]
8public List<DataModel> AdoNet_ReadAll()
9{
10 var results = new List<DataModel>();
11
12 using (var connection = new SqlConnection(ConnectionString))
13 {
14 connection.Open();
15 var command = new SqlCommand("SELECT Id, Name, Quantity FROM DataModels", connection);
16
17 using (var reader = command.ExecuteReader())
18 {
19 while (reader.Read())
20 {
21 results.Add(new DataModel
22 {
23 Id = reader.GetInt32(0),
24 Name = reader.GetString(1),
25 Quantity = reader.GetInt32(2)
26 });
27 }
28 }
29 }
30
31 return results;
32}
Ergebnisse:
Das Abrufen eines einzelnen Datensatzes nach ID ist einehäufige Operation in Web-Anwendungen.
EF Core Implementierung:
1[Benchmark]
2public DataModel? EFCore_SingleById()
3{
4 int targetId = RecordCount / 2;
5 return _dbContext.DataModels
6 .AsNoTracking()
7 .FirstOrDefault(d => d.Id == targetId);
8}
9
10ADO.NET Implementierung:
11[Benchmark]
12public DataModel? AdoNet_SingleById()
13{
14 int targetId = RecordCount / 2;
15
16 using (var connection = new SqlConnection(ConnectionString))
17 {
18 connection.Open();
19 var command = new SqlCommand(
20 "SELECT Id, Name, Quantity FROM DataModels WHERE Id = @Id",
21 connection);
22 command.Parameters.AddWithValue("@Id", targetId);
23
24 using (var reader = command.ExecuteReader())
25 {
26 if (reader.Read())
27 {
28 return new DataModel
29 {
30 Id = reader.GetInt32(0),
31 Name = reader.GetString(1),
32 Quantity = reader.GetInt32(2)
33 };
34 }
35 }
36 }
37 return null;
38}
Ergebnisse:
ADO.NET ist konsistent schneller, besonders beigrößeren Tabellen (71% Speedup bei 10.000 Datensätzen). <dieSpeicherallokation ist mit 4,15 KB vs. 10,13 KB deutlich geringer – einwichtiger Faktor bei High-Frequency-Operationen wie API-Endpoints.
EF-Core-Implementierung:
1[Benchmark]
2public void EFCore_InsertSingle()
3{
4 using (var context = new BenchmarkDbContext())
5 {
6 var model = new DataModel
7 {
8 Name = "TestInsert",
9 Quantity = 999
10 };
11 context.DataModels.Add(model);
12 context.SaveChanges();
13
14 context.DataModels.Remove(model);
15 context.SaveChanges();
16 }
17}
ADO.NET-Implementierung:
1[Benchmark]
2public void AdoNet_InsertSingle()
3{
4 int insertedId;
5
6 using (var connection = new SqlConnection(ConnectionString))
7 {
8 connection.Open();
9
10 var insertCmd = new SqlCommand(
11 "INSERT INTO DataModels (Name, Quantity) OUTPUT INSERTED.Id VALUES (@Name, @Quantity)",
12 connection);
13 insertCmd.Parameters.AddWithValue("@Name", "TestInsert");
14 insertCmd.Parameters.AddWithValue("@Quantity", 999);
15 insertedId = (int)insertCmd.ExecuteScalar();
16
17 var deleteCmd = new SqlCommand("DELETE FROM DataModels WHERE Id = @Id", connection);
18 deleteCmd.Parameters.AddWithValue("@Id", insertedId);
19 deleteCmd.ExecuteNonQuery();
20 }
21}
Ergebnisse:
ADO.NET ist 2-5x schneller und benötigt 95% wenigerSpeicher. Der EF Core-Overhead entsteht durch Context-Initialisierung, ChangeTracking und zwei SaveChanges() Aufrufe. Für Bulk-Inserts oderLogging-Operationen ist ADO.NET klar überlegen.
EF Core-Implementierung:
1[Benchmark]
2public void EFCore_UpdateSingle()
3{
4 using (var context = new BenchmarkDbContext())
5 {
6 int targetId = RecordCount / 2;
7 var model = context.DataModels.Find(targetId);
8 if (model != null)
9 {
10 model.Quantity = 12345;
11 context.SaveChanges();
12
13 model.Quantity = targetId * 10;
14 context.SaveChanges();
15 }
16 }
17}
ADO.NET-Implementierung:
1[Benchmark]
2public void AdoNet_UpdateSingle()
3{
4 int targetId = RecordCount / 2;
5
6 using (var connection = new SqlConnection(ConnectionString))
7 {
8 connection.Open();
9
10 var updateCmd = new SqlCommand(
11 "UPDATE DataModels SET Quantity = @Quantity WHERE Id = @Id",
12 connection);
13 updateCmd.Parameters.AddWithValue("@Id", targetId);
14 updateCmd.Parameters.AddWithValue("@Quantity", 12345);
15 updateCmd.ExecuteNonQuery();
16
17 var resetCmd = new SqlCommand(
18 "UPDATE DataModels SET Quantity = @Quantity WHERE Id = @Id",
19 connection);
20 resetCmd.Parameters.AddWithValue("@Id", targetId);
21 resetCmd.Parameters.AddWithValue("@Quantity", targetId * 10);
22 resetCmd.ExecuteNonQuery();
23 }
24}
Ergebnisse:
ADO.NET ist bis zu 5.18x schneller bei 10.000Datensätzen und verbraucht 96% weniger Speicher. EF Core muss hier denDatensatz laden, tracken und zwei Mal SaveChanges() durchführen - einerheblicher Overhead für einfache Updates.
Nutzen Sie EF Core, wenn:
Nutzen Sie ADO.NET, wenn:
Hybrid‑Ansatz:
Die Benchmarks zeigen eindeutig: ADO.NET ist bei allen Operationen schneller und speichereffizienter als EF Core. Der Performance‑Vorteil reicht von 8 % bei kleinen Read‑All‑Operationen bis zu über 500 % bei großen Updates. Gleichzeitig ist der Speicherverbrauch bei ADO.NET durchweg deutlich niedriger.
Für typische Business‑Anwendungen ist EF Core aufgrund höherer Entwicklerproduktivität, Wartbarkeit und Typsicherheit meist die richtige Wahl, da Performance‑Unterschiede im Bereich von Mikrosekunden im Vergleich zu Netzwerk‑Latenz und Rendering‑Zeiten vernachlässigbar sind.
Empfehlung: Starten Sie mit EF Core und optimieren Sie gezielt mit ADO.NET, sobald Profiling konkrete Performance‑Bottlenecks aufzeigt. Ein pragmatischer Hybrid‑Ansatz kombiniert die Vorteile beider Technologien.
Nutzen Sie BenchmarkDotNet, um die Performance‑Charakteristik Ihrer eigenen Anwendung zu messen. Die dargestellten Benchmarks dienen als Ausgangspunkt – individuelle Datenmodelle, Queries und Hardware können zu anderen Ergebnissen führen. Messen Sie, bevor Sie optimieren!

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 Erstberatung in einem unverbindlichen Austausch.