Trudny / egzaminacyjny · lekcja 15
Entity Framework Core — wprowadzenie do bazy danych w ASP.NET Core
Dotychczasowe przykłady w tym dziale trzymały dane "na sztywno" w pamięci (listy w kodzie C#) — znikające przy każdym restarcie aplikacji. Prawdziwa aplikacja webowa potrzebuje trwałej bazy danych. Entity Framework Core (EF Core) to oficjalne narzędzie Microso...
Zacznij tutaj
Po co się tego uczymy?
Wprowadzenie
Teoria
ORM (Object-Relational Mapper) to warstwa tłumacząca między światem OBIEKTÓW C# (klasy, właściwości, listy) a światem RELACYJNEJ bazy danych (tabele, wiersze, kolumny, klucze obce) — piszesz kod w C#, a EF Core w tle generuje i wykonuje odpowiednie zapytania SQL. To nie zwalnia z rozumienia SQL (dział "Bazy danych i SQL" pozostaje fundamentem), ale znacznie przyspiesza codzienną pracę i redukuje liczbę błędów wynikających z ręcznego sklejania zapytań.
DbContext — centralna klasa EF Core, reprezentująca POŁĄCZENIE z bazą danych i ZBIÓR wszystkich tabel dostępnych w aplikacji. Każda właściwość typu DbSet<T> odpowiada JEDNEJ tabeli w bazie — np. DbSet<Produkt> Produkty { get; set; } reprezentuje tabelę Produkty, gdzie każdy wiersz to jeden obiekt klasy Produkt.
Podejście Code First. Kurs bitedu.pl uczy podejścia "Code First" — NAJPIERW piszesz klasy C# (modele), a EF Core na ich podstawie TWORZY strukturę bazy danych (tabele, kolumny, klucze) — to odwrotność podejścia "Database First", gdzie baza już istnieje, a klasy generuje się z niej automatycznie.
Migracje — kontrola wersji struktury bazy danych. Zamiast ręcznie pisać CREATE TABLE, EF Core generuje migracje — pliki C# opisujące ZMIANY w strukturze bazy (dodanie tabeli, dodanie kolumny), które można zastosować (Update-Database) albo cofnąć. Podstawowe polecenia (w Konsoli Menedżera Pakietów w Visual Studio albo dotnet ef w terminalu):
| Polecenie | Działanie |
|---|---|
Add-Migration NazwaMigracji | tworzy nowy plik migracji na podstawie zmian w klasach modeli od ostatniej migracji |
Update-Database | stosuje WSZYSTKIE niezastosowane jeszcze migracje — faktycznie tworzy/zmienia tabele w bazie |
Remove-Migration | usuwa OSTATNIĄ, jeszcze niezastosowaną migrację (np. gdy zauważysz w niej błąd przed jej zastosowaniem) |
Connection string (ciąg połączenia z bazą danych) zapisuje się w appsettings.json, a rejestruje w Program.cs: builder.Services.AddDbContext<MojaBazaContext>(options => options.UseSqlite(connectionString)). Kurs bitedu.pl (konsekwentnie z resztą działów) korzysta z SQLite jako silnika bazy — ten sam lekki, bezserwerowy silnik, którego uczyłeś się w dziale MAUI, tylko teraz osadzony w aplikacji webowej zamiast mobilnej.
Podstawowe operacje (CRUD) przez DbContext: context.Produkty.ToListAsync() (SELECT wszystkich wierszy), context.Produkty.Add(nowyProdukt) + await context.SaveChangesAsync() (INSERT), context.Produkty.FindAsync(id) (SELECT po kluczu głównym), zmiana właściwości pobranego obiektu + SaveChangesAsync() (UPDATE), context.Produkty.Remove(produkt) + SaveChangesAsync() (DELETE) — kluczowa zasada: żadna zmiana NIE trafia do bazy, dopóki nie wywołasz SaveChangesAsync(), EF Core śledzi zmiany w pamięci i zapisuje je wszystkie naraz dopiero na to wywołanie.
Zobacz zależności
Schemat
Modele/Produkt.cs (klasa C#)
│
│ Code First: klasa OPISUJE strukturę tabeli
▼
Data/MojaBazaContext.cs (DbContext)
DbSet<Produkt> Produkty { get; set; }
│
│ Add-Migration InitialCreate
▼
Migrations/20260708_InitialCreate.cs (wygenerowany opis zmian)
│
│ Update-Database
▼
Rzeczywista tabela "Produkty" w pliku bazy SQLite
Operacje w kodzie (PageModel/Controller):
context.Produkty.ToListAsync() → SELECT * FROM Produkty
context.Produkty.Add(p) + SaveChangesAsync() → INSERT
context.Produkty.FindAsync(id) → SELECT ... WHERE Id = @id
zmiana właściwości + SaveChangesAsync() → UPDATE
context.Produkty.Remove(p) + SaveChangesAsync() → DELETE
Połącz z praktyką
Przykład z życia
Sklep internetowy przechowujący tysiące produktów potrzebuje prawdziwej bazy danych, a nie listy w pamięci znikającej przy każdym restarcie serwera — Entity Framework Core pozwala zarządzać taką bazą przez wygodne, obiektowe API w C#, zachowując jednocześnie pełną moc relacyjnej bazy danych pod spodem (te same tabele, klucze, zapytania SQL, które poznałeś w dziale "Bazy danych i SQL").