0Pricing
C# Academy · Lekcja

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 DB

Dodawanie 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 transaction

Odczyt: 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=orderId

Aktualizowanie: 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=orderId

Usuwanie: 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

  1. Podstawy DbContext i DbSet
  2. Migracje i zarządzanie schematem
  3. Operacje CRUD z EF Core
  4. Relacje: jeden-do-wielu i wiele-do-wielu
← Powrót do C# Academy