Holger Schwichtenberg
Effizienter Datenzugriff mit Entity Framework Core
Datenbankprogrammierung mit C# für .NET Framework, .NET Core und Xamarin
Inhalt
7
Vorwort
17
Über den Autor
19
1 Einleitung
21
1.1 Programmiersprache in diesem Buch
21
1.2 Fallbeispiele in diesem Buch
21
1.2.1 Entitäten
22
1.3 Anwendungsarten in diesem Buch
25
1.4 Hilfsroutinen zur Konsolenausgabe
26
1.5 Programmcodebeispiel zum Download
30
2 Was ist Entity Framework Core?
33
2.1 Was ist ein Objekt-Relationaler Mapper?
33
2.2 ORM in der .NET-Welt
35
2.3 Versionsgeschichte von Entity Framework Core
36
2.4 Unterstützte Betriebssysteme
37
2.5 Unterstützte .NET-Versionen
37
2.6 Unterstützte Visual Studio-Versionen
38
2.7 Unterstützte Datenbanken
39
2.8 Funktionsumfang von Entity Framework Core
40
2.9 Funktionen, die dauerhaft entfallen
41
2.10 Funktionen, die Microsoft bald nachrüsten will
41
2.11 Hohe Priorität, aber nicht kritisch
42
2.12 Neue Funktionen in Entity Framework Core
43
2.13 Einsatzszenarien
44
3 Installation von Entity Framework Core
47
3.1 Nuget-Pakete
47
3.2 Paketinstallation
50
3.3 Aktualisierung auf eine neue Version
54
4 Konzepte von Entity Framework Core
59
4.1 Vorgehensmodelle bei Entity Framework Core
59
4.2 Artefakte bei Entity Framework Core
61
5 Reverse Engineering bestehender Datenbanken
63
5.1 Reverse Engineering mit PowerShell-Befehlen
64
5.2 Codegenerierung
67
5.3 .NET Core-Tool
74
5.4 Schwächen des Reverse Engineering
76
6 Forward Engineering für neue Datenbanken
77
6.1 Regeln für die selbsterstellten Entitätsklassen
79
6.1.1 Properties
79
6.1.2 Datentypen
79
6.1.3 Beziehungen (Master-Detail)
79
6.1.4 Vererbung
81
6.1.5 Primärschlüssel
81
6.1.6 Beispiele
81
6.2 Regeln für die selbsterstellte Kontextklasse
84
6.2.1 Nuget-Pakete
84
6.2.2 Basisklasse
85
6.2.3 Konstruktor
85
6.2.4 Beispiel
85
6.2.5 Provider und Verbindungszeichenfolge
86
6.2.6 Eigene Verbindungen
87
6.2.7 Thread-Sicherheit
87
6.3 Regeln für die Datenbankschemagenerierung
87
6.4 Beispiel-Client
88
6.5 Anpassung per Fluent-API (OnModelCreating())
89
6.6 Das erzeugte Datenmodell
91
7 Anpassung des Datenbankschemas
93
7.1 Persistente versus transiente Klassen
94
7.2 Namen im Datenbankschema
95
7.3 Reihenfolge der Spalten in einer Tabelle
95
7.4 Spaltentypen/Datentypen
96
7.5 Pflichtfelder und optionale Felder
97
7.6 Feldlängen
97
7.7 Primärschlüssel
98
7.8 Beziehungen und Fremdschlüssel
98
7.9 Optionale Beziehungen und Pflichtbeziehungen
99
7.10 Uni- und Bidirektionale Beziehungen
101
7.11 1:1-Beziehungen
102
7.12 Indexe festlegen
103
7.13 Weitere Syntaxoptionen für das Fluent-API
105
7.13.1 Sequentielle Konfiguration
105
7.13.2 Strukturierung durch Statement Lambdas
105
7.13.3 Strukturierung durch Unterroutinen
106
7.13.4 Strukturierung durch Konfigurationsklassen
107
7.14 Massenkonfiguration mit dem Fluent-API
108
8 Datenbankschemamigrationen
111
8.1 Anlegen der Datenbank zur Laufzeit
111
8.2 Schemamigrationen zur Entwicklungszeit
112
8.3 Befehle für die Schemamigrationen
112
8.4 ef.exe
113
8.5 Add-Migration
114
8.6 Update-Database
118
8.7 Script-Migration
119
8.8 Weitere Migrationsschritte
119
8.9 Migrationsszenarien
120
8.10 Weitere Möglichkeiten
121
8.11 Schemamigrationen zur Laufzeit
123
9 Daten lesen mit LINQ
125
9.1 Kontextklasse
125
9.2 LINQ-Abfragen
126
9.3 Schrittweises Zusammensetzung von LINQ-Abfragen
128
9.4 Repository-Pattern
129
9.5 Einsatz von var
130
9.6 LINQ-Abfragen mit Paging
131
9.7 Projektionen
133
9.8 Abfrage nach Einzelobjekten
134
9.9 Laden anhand des Primärschlüssels mit Find()
135
9.10 LINQ im RAM statt in der Datenbank
135
9.11 Umgehung für das GroupBy-Problem
139
9.11.1 Mapping auf Nicht-Entitätstypen
139
9.11.2 Entitätsklasse für die Datenbanksicht anlegen
140
9.11.3 Einbinden der Entitätsklasse in die Kontextklasse
140
9.11.4 Verwendung der Pseudo-Entitätsklasse
141
9.11.5 Herausforderung: Migrationen
141
9.11.6 Gruppierungen mit Datenbanksichten
143
9.12 Kurzübersicht über die LINQ-Syntax
143
9.12.1 Einfache SELECT-Befehle (Alle Datensätze)
145
9.12.2 Bedingungen (where)
145
9.12.3 Bedingungen mit Mengen (in)
146
9.12.4 Sortierungen (orderby)
146
9.12.5 Paging (Skip() und Take())
147
9.12.6 Projektion
147
9.12.7 Aggregatfunktionen (Count(), Min(), Max(), Average(), Sum())
148
9.12.8 Gruppierungen (GroupBy)
149
9.12.9 Einzelobjekte (SingleOrDefault(), FirstOrDefault())
150
9.12.10 Verbundene Objekte (Include())
151
9.12.11 Inner Join (Join)
152
9.12.12 Cross Join (Kartesisches Produkt)
153
9.12.13 Join mit Gruppierung
153
9.12.14 Unter-Abfragen (Sub-Select)
154
10 Objektbeziehungen und Ladestrategien
157
10.1 Standardverhalten
157
10.2 Kein Lazy Loading
158
10.3 Eager Loading
160
10.4 Explizites Nachladen (Explicit Loading)
163
10.5 Preloading mit Relationship Fixup
165
10.6 Details zum Relationship Fixup
170
11 Einfügen, Löschen und Ändern
171
11.1 Speichern mit SaveChanges()
171
11.2 Änderungsverfolgung auch für Unterobjekte
174
11.3 Das Foreach-Problem
175
11.4 Objekte hinzufügen mit Add()
176
11.5 Verbundene Objekte anlegen
178
11.6 Verbundene Objekte ändern/Relationship Fixup
181
11.7 Widersprüchliche Beziehungen
184
11.8 Zusammenfassen von Befehlen (Batching)
189
11.9 Objekte löschen mit Remove()
190
11.10 Löschen mit einem Attrappen-Objekt
191
11.11 Massenlöschen
192
11.12 Datenbanktransaktionen
193
11.13 Change Tracker abfragen
196
11.13.1 Zustand eines Objekts
196
11.13.2 Liste aller geänderten Objekte
198
12 Datenänderungskonflikte (Concurrency)
201
12.1 Rückblick
201
12.2 Im Standard keine Konflikterkennung
202
12.3 Optimistisches Sperren/ Konflikterkennung
204
12.4 Konflikterkennung für alle Eigenschaften
205
12.5 Konflikteinstellung per Konvention
206
12.6 Fallweise Konflikteinstellung
207
12.7 Zeitstempel (Timestamp)
208
12.8 Konflikte auflösen
210
12.9 Pessimistisches Sperren bei Entity Framework Core
214
13 Protokollierung (Logging)
219
13.1 Verwendung der Erweiterungsmethode Log()
219
13.2 Implementierung der Log()-Erweiterungsmethode
221
13.3 Protokollierungskategorien
224
14 Asynchrone Programmierung
225
14.1 Asynchrone Erweiterungsmethoden
225
14.2 ToListAsync()
225
14.3 SaveChangesAsync()
227
14.4 ForeachAsync()
228
15 Dynamische LINQ-Abfragen
231
15.1 Schrittweises Zusammensetzen von LINQ-Abfragen
231
15.2 Expression Trees
233
15.3 Dynamic LINQ
236
16 Daten lesen und ändern mit SQL, Stored Procedures und Table Valued Functions
239
16.1 Abfragen mit FromSql()
239
16.2 Zusammensetzbarkeit von LINQ und SQL
241
16.3 Globale Abfragefilter bei SQL-Abfragen (ab Version 2.0)
243
16.4 Stored Procedures und Table Valued Functions
244
16.5 Globale Abfragefilter bei Stored Procedures und Table Valued Functions
245
16.6 Nicht-Entitätsklassen als Ergebnismenge
246
16.7 SQL-DML-Befehle ohne Resultset
248
17 Weitere Tipps und Tricks zum Mapping
249
17.1 Shadow Properties
249
17.1.1 Automatische Shadow Properties
249
17.1.2 Festlegung eines Shadow Property
250
17.1.3 Ausgabe aller Shadow Properties einer Entitätsklasse
250
17.1.4 Lesen und Ändern eines Shadow Property
251
17.1.5 LINQ-Abfragen mit Shadow Properties
252
17.1.6 Praxisbeispiel: Automatisches Setzen des Shadow Property bei jedem Speichern
252
17.2 Tabellenaufteilung (Table Splitting)
253
17.3 Berechnete Spalten (Computed Columns)
256
17.3.1 Automatisches SELECT
257
17.3.2 Praxistipp: Spalten mit einer Berechnungsformel anlegen
257
17.3.3 Spalten mit einer Berechnungsformel nutzen
259
17.3.4 Spalten mit einer Berechnungsformel beim Reverse Engineering
261
17.4 Standardwerte (Default Values)
262
17.4.1 Standardwerte beim Forward Engineering festlegen
262
17.4.2 Standardwerte verwenden
263
17.4.3 Praxistipp: Standardwerte schon beim Anlegen des Objekts vergeben
265
17.4.4 Standardwerte beim Reverse Engineering
266
17.5 Sequenzobjekte (Sequences)
267
17.5.1 Erstellen von Sequenzen beim Forward Engineering
267
17.5.2 Sequenzen im Einsatz
268
17.6 Alternative Schlüssel
271
17.6.1 Alternative Schlüssel definieren
272
17.6.2 Alternative Schlüssel im Einsatz
274
17.7 Kaskadierendes Löschen (Cascading Delete)
275
17.8 Abbildung von Datenbanksichten (Views)
278
17.8.1 Datenbanksicht anlegen
279
17.8.2 Entitätsklasse für die Datenbanksicht anlegen
279
17.8.3 Einbinden der Entitätsklasse in die Kontextklasse
279
17.8.4 Verwendung der Datenbanksicht
280
17.8.5 Herausforderung: Migrationen
280
18 Weitere Tipps und Tricks zu LINQ
283
18.1 Globale Abfragefilter (ab Version 2.0)
283
18.1.1 Filter definieren
283
18.1.2 Filter nutzen
284
18.1.3 Praxistipp: Filter ignorieren
285
18.2 Zukünftige Abfragen (Future Queries)
285
19 Leistungsoptimierung (Performance Tuning)
287
19.1 Vorgehensmodell zur Leistungsoptimierung bei Entity Framework Core
287
19.2 Best Practices für Ihre eigenen Leistungstests
288
19.3 Leistungsvergleich verschiedener Dattenzugriffstechniken in .NET
288
19.4 Objektzuweisung optimieren
290
19.5 Massenoperationen
292
19.5.1 Einzellöschen
292
19.5.2 Optimierung durch Batching
293
19.5.3 Löschen ohne Laden mit Pseudo-Objekten
294
19.5.4 Einsatz von klassischem SQL anstelle des Entity Framework Core-APIs
295
19.5.5 Lamdba-Ausdrücke für Massenlöschen mit EFPlus
297
19.5.6 Massenaktualisierung mit EFPlus
298
19.6 Leistungsoptimierung durch No-Tracking
299
19.6.1 No-Tracking aktivieren
300
19.6.2 No-Tracking fast immer möglich
302
19.6.3 No-Tracking im änderbaren Datagrid
305
19.6.4 QueryTrackingBehavior und AsTracking()
306
19.6.5 Best Practices
308
19.7 Auswahl der besten Ladestrategie
308
19.8 Zwischenspeicherung (Caching)
309
19.8.1 MemoryCache
309
19.8.2 Abstraktion CacheManager
312
19.9 Second-Level-Caching mit EFPlus
316
19.9.1 Einrichten des Second-Level-Cache
317
19.9.2 Verwenden des Second-Level-Cache
317
20 Softwarearchitektur mit Entity Framework Core
321
20.1 Monolithisches Modell
321
20.2 Entity Framework Core als Datenzugriffsschicht
322
20.3 Reine Geschäftslogik
324
20.4 Geschäftsobjekt- und ViewModel-Klassen
325
20.5 Verteilte Systeme
326
20.6 Fazit
329
21 Zusatzwerkzeuge
331
21.1 Entity Framework Core Power Tools
331
21.1.1 Funktionsüberblick
331
21.1.2 Reverse Engineering mit Entity Framework Core Power Tools
332
21.1.3 Diagramme mit Entity Framework Core Power Tools
336
21.2 LINQPad
337
21.2.1 Aufbau von LINQPad
338
21.2.2 Datenquellen einbinden
339
21.2.3 LINQ-Befehle ausführen
342
21.2.4 Speichern
345
21.2.5 Weitere LINQPad-Treiber
345
21.2.6 Interaktive Programmcodeeingabe
346
21.2.7 Fazit zu LINQPad
347
21.3 Entity Developer
347
21.3.1 Reverse Engineering mit Entity Developer
348
21.3.2 Forward Engineering mit Entity Developer
359
21.4 Entity Framework Profiler
364
21.4.1 Einbinden des Entity Framework Profilers
366
21.4.2 Befehle überwachen mit Entity Framework Profiler
366
21.4.3 Warnungen vor potenziellen Problemen
369
21.4.4 Analysefunktionen
369
21.4.5 Fazit zu Entity Framework Profiler
370
22 Zusatzkomponenten
371
22.1 Entity Framework Plus (EFPlus)
371
22.2 Second-Level-Caching mit EFSecondLevelCache.Core
372
22.3 Objekt-Objekt-Mapping und AutoMapper
372
22.3.1 Objekt-Objekt-Mapping per Reflection
374
22.3.2 AutoMapper
377
22.3.3 Beispiel
378
22.3.4 Abbildungen konfigurieren
379
22.3.5 Abbildung ausführen mit Map()
380
22.3.6 Abbildungskonventionen
381
22.3.7 Profilklassen
383
22.3.8 Verbundene Objekte
383
22.3.9 Manuelle Abbildungen
384
22.3.10 Typkonvertierungen
386
22.3.11 Objektmengen
388
22.3.12 Vererbung
389
22.3.13 Generische Klassen
391
22.3.14 Zusatzaktionen vor und nach dem Mapping
394
22.3.15 Geschwindigkeit
395
22.3.16 Fazit zu AutoMapper
396
23 Praxislösungen
399
23.1 Entity Framework Core in einer ASP.NET Core-Anwendung
399
23.1.1 Das Fallbeispiel “MiracleList“ 379
14
23.1.2 Architektur
403
23.1.3 Entitätsklassen
405
23.1.4 Entity Framework Core-Kontextklasse
407
23.1.5 Lebensdauer der Kontextklasse in ASP.NET Core-Anwendungen
409
23.1.6 Geschäftslogik
410
23.1.7 WebAPI
418
23.1.8 Verwendung von Entity Framework Core per Dependency Injection
428
23.1.9 Praxistipp: Kontextinstanzpooling (DbContext Pooling)
431
23.2 Entity Framework Core in einer Universal Windows Platform App
432
23.2.1 Das Fallbeispiel “MiracleList Light“ 412
15
23.2.2 Architektur
433
23.2.3 Entitätsklassen
435
23.2.4 Entity Framework Core-Kontextklasse
436
23.2.5 Startcode
436
23.2.6 Erzeugte Datenbank
437
23.2.7 Datenzugriffscode
439
23.2.8 Benutzeroberfläche
443
23.3 Entity Framework Core in einer Xamarin-Cross-Platform-App
444
23.3.1 Das Fallbeispiel “MiracleList Light“ 424
15
23.3.2 Architektur
446
23.3.3 Entitätsklassen
448
23.3.4 Entity Framework Core-Kontextklasse
448
23.3.5 Startcode
450
23.3.6 Erzeugte Datenbank
450
23.3.7 Datenzugriffscode
450
23.3.8 Benutzeroberfläche
454
23.4 N:M-Beziehungen zu sich selbst
455
24 Quellen im Internet
461
Index
463
Leere Seite
2
© 2009-2024 ciando GmbH