Sofern mit ASP.NET Core Daten über eine Datenbank verwaltet werden sollen, ist das Entity Framework eine gute Wahl, um als Schnittstelle zwischen Datenbank und Anwendung zu dienen. Im Folgenden findet sich eine kurze Anleitung zur Erstellung einer Konsolenanwendung, die anschließend einfache CRUD-Befehle mithilfe des Entity Frameworks ausführen kann.
Zu Beginn wird ein neues „Konsolen-App (.NET Core)“-Projekt erstellt.
Um im Nachhinein Daten in eine Datenbank schreiben zu können, ist es notwendig, das NuGet-Paket „Microsoft.EntityFrameworkCore.Sqlite“ zu installieren.
Im weiteren Verlauf werden dann die beiden Datenmodell-Klassen „Genre“ und „Book“ angelegt:
1using System.Collections.Generic;
2
3namespace EFBasics
4{
5 public class Genre
6 {
7 public int Id { get; set; }
8 public string Title { get; set; }
9 public List<Book> Books { get; } = new List<Book>();
10 public override string ToString()
11 {
12 return "Genre: " + Id + " - " + Title;
13 }
14 }
15}
1namespace EFBasics
2{
3 public class Book
4 {
5 public int Id { get; set; }
6 public string Title { get; set; }
7 public int GenreId { get; set; }
8 public Genre Genre { get; set; }
9 public override string ToString()
10 {
11 return "Book: " + Id + " - " + Title;
12 }
13 }
14}
Nachdem beide Datenmodell-Klassen angelegt sind, müssen diese dem sogenannten Datenbank-Kontext hinzugefügt werden. Dafür wird eine neue Klasse namens EFBasicContext
benötigt. Unter diesem „Kontext“ werden die beiden Klassen Genre
und Book
als DbSet
zusammengefasst. Um den Datenbank-Kontext einer konkreten Datenbank zuordnen zu können, wird am Ende der Klasse EFBasicContext
ein sogenannter ConnectionString angegeben, wie im Folgenden dargestellt:
1using Microsoft.EntityFrameworkCore;
2namespace EFBasics
3{
4 public class EFBasicsContext : DbContext
5 {
6 public DbSet<Genre> Genres { get; set; }
7 public DbSet<Book> Books { get; set; }
8 protected override void OnConfiguring(DbContextOptionsBuilder options)
9 => options.UseSqlite("Data Source=efbasics.db");
10 }
11}
Diese Phase widmet sich der Datenbank-Abfrage. Hierzu wird ein Rahmen innerhalb einer Programm-Klasse benötigt, um zwischen verschiedenen Befehlen auswählen zu können. Für das folgende Beispiel wurde eine While-Schleife verwendet, die so lange durchlaufen wird, bis ein Befehl zum Abbruch des Durchlaufs gegeben wird (Eingabe der 5).
Die bereits erwähnten CRUD-Befehle sind anschließend für unterschiedlichste Optionen und Möglichkeiten implementiert worden und können im nachfolgenden Code-Snippet nachvollzogen werden.
Über den Datenbank-Kontext ist es möglich, verschiedene Tabellen auszuwählen, die vorher im Datenbank-Kontext implementiert wurden.
Mit der Funktion Add
können neue Einträge in die Tabellen hinzugefügt werden. Mit Hilfe der Funktion Delete
können diese problemlos entfernt werden. Besonders wichtig ist es, die Funktion SaveChanges
zu verwenden, um sicherzustellen, dass alle Änderungen und Anpassungen gespeichert werden.
1class Program
2{
3 static void Main(string[] args)
4 {
5 using (var db = new EFBasicsContext())
6 {
7 bool done = false;
8 while (!done)
9 {
10 Console.WriteLine("Wählen Sie einen Befehl aus:");
11 Console.WriteLine("Show all Data (0), Create (1), Read (2), Update (3), Delete (4), Break (5)");
12 var x = Convert.ToInt32(Console.ReadLine());
13 switch (x)
14 {
15 case 0: // Show Data
16 {
17 var myGenresQuery = db.Genres
18 .Include(c => c.Books)
19 .AsQueryable();
20 var myGenres = myGenresQuery.ToList();
21 foreach (var myGenre in myGenres)
22 {
23 Console.WriteLine(myGenre.ToString());
24 foreach (var myBook in myGenre.Books)
25 Console.WriteLine("└───" + myBook.ToString());
26 }
27 }
28 break;
29 case 1: // Create
30 {
31 Console.WriteLine("Create");
32 db.Add(new Genre { Title = "Thriller" });
33 db.SaveChanges();
34 }
35 break;
36 case 2: // Read
37 {
38 Console.WriteLine("Read");
39 var genre = db.Genres.FirstOrDefault();
40 Console.WriteLine(genre.ToString());
41 }
42 break;
43 case 3: // Update
44 {
45 Console.WriteLine("Update");
46 var genre = db.Genres.FirstOrDefault();
47 genre.Title = "Horror";
48 genre.Books.Add(new Book { Title = "Shining" });
49 db.SaveChanges();
50 }
51 break;
52 case 4: // Delete
53 {
54 Console.WriteLine("Delete the genre");
55 var genre = db.Genres.FirstOrDefault();
56 db.Remove(genre);
57 db.SaveChanges();
58 }
59 break;
60 case 5:
61 done = true;
62 break;
63 default:
64 break;
65 }
66 }
67 }
68 }
69}
Der Unterschied zwischen den beiden Varianten liegt lediglich in ihrer Syntax. Daher ist es für die weitere Programmierung keine Frage der Entscheidung, da mit beiden Varianten gearbeitet werden kann.
1// LINQ with Method Syntax
2var book1 = db.Books.SingleOrDefault(p => p.Id == id);
3
4// LINQ with Query Syntax
5var book2 = (from p in db.Books
6 where p.Id == id
7 select p).SingleOrDefault();
Zusammenfassend lässt sich sagen, dass sich die Grundlagen des Entity Frameworks schnell verstehen und erlernen lassen. Jedoch ist nicht auszuschließen, dass es bei der Programmierung schnell komplizierter werden kann, insbesondere sobald die Entitäten komplexer oder die Abfragen sehr umfangreich werden. Daher ist es wichtig zu beachten, wann man sich noch innerhalb eines Datenbank-Kontextes bewegt sowie bei größeren Abfragen Daten nur einmal per Query zu laden.
Potenzielle Fehler können schnell entstehen, beispielsweise wenn eine Query doppelt versendet wird:
1var myGenresQuery = db.Genres.AsQueryable();
2var myGenres = myGenresQuery.ToList();
3var myGenres2 = myGenresQuery.ToList();