Surowy SQL, procedury składowane i interpolacja
Bezpiecznie wykonuj surowy SQL za pomocą FromSqlRaw, FromSqlInterpolated i procedur składowanych, unikając SQL injection.
Surowy SQL, procedury składowane i interpolacja to bezpłatna lekcja C# Academy na CoddyKit. To lekcja 2 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.
Kiedy używać surowego SQL w EF Core
Większość zapytań działa poprawnie z LINQ, ale niektóre scenariusze wymagają surowego SQL: złożonej analityki, funkcji specyficznych dla dostawcy, procedur składowanych lub zapytań o krytycznym znaczeniu dla wydajności, które LINQ tłumaczy nieoptymalnie.
EF Core udostępnia bezpieczne sposoby używania surowego SQL bez rezygnowania z bezpieczeństwa.
FromSqlRaw: bezpieczne zapytania z parametrami
FromSqlRaw wykonuje surowy SQL i mapuje wyniki z powrotem na encje. Należy zawsze używać symboli zastępczych {0} — nigdy konkatenacji ciągów — aby zapobiec SQL injection.
// SAFE: parameterized
var products = await _db.Products
.FromSqlRaw("SELECT * FROM Products WHERE Price > {0}", 100m)
.ToListAsync();
// DANGEROUS: never do this
// FromSqlRaw("SELECT * FROM Products WHERE Price > " + price)FromSqlInterpolated: bezpieczeństwo interpolacji
FromSqlInterpolated przyjmuje interpolowany ciąg C#. EF Core automatycznie konwertuje interpolowane wartości na parametry SQL, zapewniając bezpieczeństwo i czytelność.
decimal minPrice = 100m;
string category = "Electronics";
var products = await _db.Products
.FromSqlInterpolated(
$"SELECT * FROM Products WHERE Price > {minPrice} AND Category = {category}")
.OrderBy(p => p.Name)
.ToListAsync();
// Values become @p0, @p1 parameters automaticallyŁączenie operatorów LINQ po FromSql
Po FromSql można łączyć operatory LINQ. EF Core opakowuje surowy SQL jako podzapytanie i nakłada na nie operatory LINQ, co jest przydatne przy dodawaniu filtrowania lub stronicowania.
decimal min = 50m;
var page = await _db.Products
.FromSqlInterpolated($"SELECT * FROM Products WHERE Price > {min}")
.Where(p => p.IsActive) // additional LINQ filter
.OrderBy(p => p.Price)
.Skip(0).Take(20) // pagination
.ToListAsync();
// Generates: SELECT ... FROM (raw SQL) AS p WHERE ...Wykonywanie procedur składowanych
Procedury składowane zwracające wiersze encji należy wywoływać za pomocą FromSqlRaw. W przypadku procedur, które nie zwracają wierszy, na przykład INSERT/UPDATE, należy użyć ExecuteSqlRawAsync.
// Stored proc returning Products
var products = await _db.Products
.FromSqlRaw("EXEC GetProductsByCategory {0}", "Books")
.ToListAsync();
// Stored proc with no return rows
await _db.Database.ExecuteSqlRawAsync(
"EXEC ArchiveOldOrders {0}",
DateTime.UtcNow.AddYears(-1));ExecuteSqlInterpolated dla instrukcji DML
ExecuteSqlInterpolated wykonuje instrukcje DML (INSERT, UPDATE, DELETE), zapewniając bezpieczeństwo interpolowanych ciągów. Zwraca liczbę zmodyfikowanych wierszy.
int days = 30;
int affected = await _db.Database.ExecuteSqlInterpolatedAsync(
$"UPDATE Orders SET Status = 'Expired' WHERE PlacedAt < {DateTime.UtcNow.AddDays(-days)}");
Console.WriteLine($"{affected} orders expired");Odpytywanie typów niebędących encjami
Należy użyć SqlQuery<T> (.NET 7+), aby odpytywać dowolne typy skalarne lub typy DTO, które nie są encjami EF Core. Nie jest wymagany obiekt DbSet.
// Query a DTO directly — no entity needed
var stats = await _db.Database
.SqlQuery<ProductStats>(
$"SELECT Category, COUNT(*) AS Count, AVG(Price) AS AvgPrice FROM Products GROUP BY Category")
.ToListAsync();
public record ProductStats(string Category, int Count, decimal AvgPrice);Typy encji bez klucza dla widoków
Widok bazy danych lub wynik surowego zapytania można zmapować na typ encji bez klucza za pomocą HasNoKey() i ToView(). Można odpytywać go tak jak obiekt DbSet, bez konieczności definiowania klucza głównego.
public class ProductSalesSummary
{
public string Category { get; set; } = "";
public int TotalSold { get; set; }
public decimal Revenue { get; set; }
}
// In OnModelCreating:
modelBuilder.Entity<ProductSalesSummary>()
.HasNoKey()
.ToView("vw_ProductSalesSummary");
// Query:
var summary = await _db.Set<ProductSalesSummary>().ToListAsync();Unikanie pułapek SQL injection
Najważniejsza zasada: nigdy nie należy łączyć danych wejściowych użytkownika z ciągami SQL. Zawsze należy używać zapytań parametryzowanych za pomocą symboli zastępczych FromSqlRaw, FromSqlInterpolated lub LINQ w EF Core.
// SAFE
var name = userInput;
var result = await _db.Products
.FromSqlInterpolated($"SELECT * FROM Products WHERE Name = {name}")
.ToListAsync();
// INJECTION RISK (never do this)
// FromSqlRaw("SELECT * FROM Products WHERE Name = '" + name + "'");Parametry wyjściowe z użyciem ADO.NET
EF Core nie obsługuje natywnie parametrów wyjściowych procedur składowanych. W takich przypadkach należy użyć ADO.NET za pośrednictwem _db.Database.GetDbConnection().
await _db.Database.OpenConnectionAsync();
var conn = _db.Database.GetDbConnection();
using var cmd = conn.CreateCommand();
cmd.CommandText = "EXEC GetOrderCount @CustomerId, @Count OUTPUT";
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter("@CustomerId", 5));
var outParam = new SqlParameter("@Count", SqlDbType.Int) { Direction = ParameterDirection.Output };
cmd.Parameters.Add(outParam);
await cmd.ExecuteNonQueryAsync();
int count = (int)outParam.Value;Praktyka: rozwiązanie awaryjne dla wyszukiwania pełnotekstowego
LINQ nie pozwala wyrażać predykatów wyszukiwania pełnotekstowego specyficznych dla bazy danych. Należy użyć FromSqlInterpolated, aby skorzystać z natywnych możliwości FREETEXT lub tsvector.
string query = "keyboard mechanical";
var results = await _db.Products
.FromSqlInterpolated(
$"SELECT * FROM Products WHERE FREETEXT(Name, {query})")
.AsNoTracking()
.Take(20)
.ToListAsync();Szybkie sprawdzenie
Dlaczego FromSqlInterpolated jest bezpieczniejsze niż konkatenacja ciągów w przypadku zapytań parametryzowanych?
Podsumowanie: surowy SQL w EF Core
Najważniejsze informacje:
FromSqlRaw: należy używać symboli zastępczych {0}; nigdy nie należy łączyć danych wejściowych użytkownika z ciągamiFromSqlInterpolated: bezpieczne interpolowane ciągi → parametry ADO.NET- Po FromSql można łączyć operatory LINQ, aby dodawać filtrowanie, sortowanie i stronicowanie
ExecuteSqlInterpolatedAsync: bezpieczne wykonywanie instrukcji DMLSqlQuery<T>: odpytywanie obiektów DTO niebędących encjami (.NET 7+)- ADO.NET należy stosować bezpośrednio w przypadku parametrów wyjściowych lub złożonych procedur składowanych
Ucz się C# dzięki korepetycjom AI — za darmo
Pisz i uruchamiaj kod w przeglądarce, otrzymuj natychmiastową pomoc od korepetytora AI dostępnego 24/7 i kontynuuj naukę w sieci lub w aplikacji.
- Kursy
- 93
- Lekcje
- 346
Często zadawane pytania
Czy lekcja „Surowy SQL, procedury składowane i interpolacja” jest bezpłatna?
Tak — pełny tekst „Surowy SQL, procedury składowane i interpolacja” 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 „Surowy SQL, procedury składowane i interpolacja”?
Bezpiecznie wykonuj surowy SQL za pomocą FromSqlRaw, FromSqlInterpolated i procedur składowanych, unikając SQL injection. Ć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 2 z 4.
Ile czasu zajmuje lekcja „Surowy SQL, procedury składowane i interpolacja”?
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
- Ładowanie eager, lazy i explicit
- Surowy SQL, procedury składowane i interpolacja
- Zapytania kompilowane i wydajność
- Globalne filtry zapytań i encje owned