Operacje CRUD z EF Core
Wykonuj operacje Create, Read, Update i Delete, korzystając ze śledzenia zmian EF Core oraz SaveChanges.
Operacje CRUD z EF Core to bezpłatna lekcja C# Academy na CoddyKit. To lekcja 3 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej C# Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs C# Academy zawiera 4 lekcji w sumie.
Przegląd operacji CRUD w EF Core
EF Core obsługuje wszystkie cztery operacje CRUD — tworzenie, odczyt, aktualizowanie i usuwanie — za pomocą połączenia mechanizmu śledzenia zmian i metody SaveChangesAsync(). Zrozumienie działania mechanizmu śledzenia zmian jest kluczem do opanowania operacji CRUD.
Tworzenie: dodawanie nowej encji
Należy użyć DbSet.Add() lub AddAsync(), aby oznaczyć encję jako Added. Podczas wywołania SaveChangesAsync() EF Core wygeneruje instrukcję INSERT i uzupełni klucz zwiększany automatycznie.
var order = new Order
{
CustomerId = 5,
PlacedAt = DateTime.UtcNow,
Status = OrderStatus.Pending
};
await _db.Orders.AddAsync(order);
await _db.SaveChangesAsync();
Console.WriteLine(order.Id); // populated by DBDodawanie grafu encji
Dodanie encji nadrzędnej wraz z encjami podrzędnymi w jednym wywołaniu powoduje wstawienie całego grafu obiektów. EF Core automatycznie ustala relacje FK.
var order = new Order
{
CustomerId = 5,
PlacedAt = DateTime.UtcNow,
Lines = new List<OrderLine>
{
new() { ProductId = 10, Quantity = 2, Price = 49.99m },
new() { ProductId = 11, Quantity = 1, Price = 19.99m }
}
};
_db.Orders.Add(order);
await _db.SaveChangesAsync();
// Inserts Order + 2 OrderLines in one transactionOdczyt: wykonywanie zapytań za pomocą LINQ
EF Core tłumaczy wyrażenia LINQ na SQL. Zapytania należy tworzyć za pomocą Where, Select, OrderBy itd., a następnie materializować je za pomocą ToListAsync lub FirstOrDefaultAsync.
// Read all pending orders for a customer
var orders = await _db.Orders
.Where(o => o.CustomerId == 5 && o.Status == OrderStatus.Pending)
.OrderByDescending(o => o.PlacedAt)
.Select(o => new OrderSummaryDto
{
Id = o.Id,
Total = o.Lines.Sum(l => l.Quantity * l.Price),
Status = o.Status.ToString()
})
.ToListAsync();Odczyt: wyszukiwanie pojedynczej encji
W przypadku odczytu pojedynczej encji należy użyć FindAsync (najpierw sprawdza mechanizm śledzenia zmian) albo FirstOrDefaultAsync / SingleOrDefaultAsync z predykatem.
// By PK (checks cache first)
var order = await _db.Orders.FindAsync(orderId);
// By predicate (always hits DB)
var latest = await _db.Orders
.Where(o => o.CustomerId == 5)
.OrderByDescending(o => o.PlacedAt)
.FirstOrDefaultAsync();Aktualizowanie: śledzenie zmian
Encje załadowane przez EF Core są śledzone. Należy bezpośrednio zmodyfikować ich właściwości i wywołać SaveChangesAsync(). EF Core wykryje różnicę i wygeneruje minimalną instrukcję UPDATE.
var order = await _db.Orders.FindAsync(orderId);
if (order is null) return;
order.Status = OrderStatus.Shipped;
order.ShippedAt = DateTime.UtcNow;
await _db.SaveChangesAsync();
// UPDATE Orders SET Status=..., ShippedAt=... WHERE Id=orderIdAktualizowanie: aktualizacja zbiorcza (EF Core 7+)
ExecuteUpdateAsync aktualizuje wiersze bezpośrednio w bazie danych, bez ładowania encji. Jest to znacznie wydajniejsze w przypadku operacji zbiorczych.
// Mark all overdue orders as Cancelled — no loading needed
await _db.Orders
.Where(o => o.Status == OrderStatus.Pending
&& o.PlacedAt < DateTime.UtcNow.AddDays(-30))
.ExecuteUpdateAsync(set => set
.SetProperty(o => o.Status, OrderStatus.Cancelled)
.SetProperty(o => o.UpdatedAt, DateTime.UtcNow));Usuwanie: usuwanie pojedynczej encji
Należy wywołać Remove() dla śledzonej encji, a następnie SaveChangesAsync(). Jeśli dostępny jest tylko identyfikator, należy najpierw ją znaleźć albo użyć ExecuteDeleteAsync.
var order = await _db.Orders.FindAsync(orderId);
if (order is null) return;
_db.Orders.Remove(order);
await _db.SaveChangesAsync();
// DELETE FROM Orders WHERE Id=orderIdUsuwanie: usuwanie zbiorcze (EF Core 7+)
ExecuteDeleteAsync wykonuje pojedynczą instrukcję SQL DELETE bez ładowania encji — idealnie nadaje się do operacji zbiorczego czyszczenia danych.
// Delete all cancelled orders older than 1 year
int deleted = await _db.Orders
.Where(o => o.Status == OrderStatus.Cancelled
&& o.PlacedAt < DateTime.UtcNow.AddYears(-1))
.ExecuteDeleteAsync();
Console.WriteLine($"Deleted {deleted} old orders");Transakcje
Wszystkie operacje w ramach pojedynczego wywołania SaveChangesAsync są objęte transakcją. W przypadku wieloetapowych operacji obejmujących wiele zapisów należy użyć jawnej transakcji.
using var transaction = await _db.Database.BeginTransactionAsync();
try
{
_db.Orders.Add(newOrder);
await _db.SaveChangesAsync();
inventory.Stock -= newOrder.Quantity;
await _db.SaveChangesAsync();
await transaction.CommitAsync();
}
catch
{
await transaction.RollbackAsync();
throw;
}Praktyczny przykład: kompletna usługa CRUD
Kompletna usługa opakowuje wszystkie operacje CRUD, zapewnia właściwą obsługę błędów i zwraca obiekty DTO, aby nie ujawniać szczegółów implementacji encji.
public async Task<OrderDto> CreateOrderAsync(CreateOrderRequest req)
{
var order = new Order { CustomerId = req.CustomerId, PlacedAt = DateTime.UtcNow };
_db.Orders.Add(order);
await _db.SaveChangesAsync();
return new OrderDto { Id = order.Id, Status = order.Status.ToString() };
}
public async Task<bool> CancelOrderAsync(int id)
{
int rows = await _db.Orders
.Where(o => o.Id == id && o.Status == OrderStatus.Pending)
.ExecuteUpdateAsync(s =>
s.SetProperty(o => o.Status, OrderStatus.Cancelled));
return rows > 0;
}Szybkie sprawdzenie
Jaka jest przewaga ExecuteUpdateAsync / ExecuteDeleteAsync nad ładowaniem encji i wywoływaniem SaveChangesAsync?
Podsumowanie: operacje CRUD w EF Core
Najważniejsze informacje:
- Add + SaveChangesAsync → INSERT; EF Core uzupełnia automatycznie generowane klucze
- Modyfikacja śledzonych encji + SaveChangesAsync → minimalna instrukcja UPDATE
- Remove + SaveChangesAsync → DELETE dla pojedynczych encji
- ExecuteUpdateAsync / ExecuteDeleteAsync → operacje zbiorcze bez ładowania encji (EF Core 7+)
- Operacje wieloetapowe należy objąć jawną transakcją, aby zapewnić niepodzielność
Często zadawane pytania
Czy lekcja „Operacje CRUD z EF Core” jest bezpłatna?
Tak — pełny tekst „Operacje CRUD z EF Core” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu C# Academy, przejdź na CoddyKit PRO. Kurs C# Academy zawiera 4 lekcji w sumie.
Co nauczysz się w „Operacje CRUD z EF Core”?
Wykonuj operacje Create, Read, Update i Delete, korzystając ze śledzenia zmian EF Core oraz SaveChanges. Ćwiczysz C# Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć C# Academy?
Nie wymagamy żadnego doświadczenia. C# Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 3 z 4.
Ile czasu zajmuje lekcja „Operacje CRUD z EF Core”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji C# Academy?
Tak. Każda lekcja C# Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Podstawy DbContext i DbSet
- Migracje i zarządzanie schematem
- Operacje CRUD z EF Core
- Relacje: jeden-do-wielu i wiele-do-wielu