Ответ
Да, в ряде сценариев работа с "сырым" SQL необходима, даже при использовании ORM вроде Entity Framework Core.
Типичные случаи и подходы:
-
Сложные аналитические запросы: Операции, которые неэффективно или невозможно выразить через LINQ (оконные функции, рекурсивные CTE, сложные агрегации).
var query = @" WITH RankedOrders AS ( SELECT CustomerId, OrderDate, TotalAmount, ROW_NUMBER() OVER (PARTITION BY CustomerId ORDER BY OrderDate DESC) as rn FROM Orders ) SELECT * FROM RankedOrders WHERE rn = 1"; var lastOrders = await _context.Orders.FromSqlRaw(query).ToListAsync(); -
Массовые операции (Bulk Operations): Для обновления/удаления большого объема данных
ExecuteSqlRawилиExecuteSqlInterpolatedэффективнее, чем загрузка сущностей в память.await _context.Database.ExecuteSqlInterpolatedAsync( $"UPDATE Products SET Price = Price * {1.1m} WHERE CategoryId = {categoryId}"); -
Работа с ADO.NET напрямую: Для максимального контроля над подключением и чтением данных.
using (var connection = new SqlConnection(_config.GetConnectionString("Default"))) { await connection.OpenAsync(); var command = new SqlCommand("SELECT Id, Name FROM Users WHERE IsActive = @isActive", connection); command.Parameters.AddWithValue("@isActive", true); // КРИТИЧНО: всегда использовать параметры! using (var reader = await command.ExecuteReaderAsync()) { while (await reader.ReadAsync()) { var id = reader.GetInt32(0); var name = reader.GetString(1); // ... обработка } } }
Важно: При любом использовании прямого SQL обязательны параметризация запросов для защиты от SQL-инъекций и анализ плана выполнения для обеспечения эффективности.
Ответ 18+ 🔞
Ну вот, опять про этот ваш SQL, прям как будто без него совсем никак! Слушай, а ты в курсе, что иногда ORM — это как ехать на работу на танке? Надёжно, блядь, непробиваемо, но бензина жрёт дохуя, и парковаться — ёперный театр!
Вот смотри, бывают же ситуации, когда этот Entity Framework просто разводит руками и говорит: «Сам, сука, разбирайся!».
Типичные случаи, когда надо лезть в это сырое мясо:
-
Запросы, от которых у LINQ мозг вытекает. Ну серьёзно, там какие-то оконные функции, рекурсивные CTE, сложнейшие агрегации. Пытаться это через LINQ выразить — это как пытаться объяснить теорию относительности мартышке. Проще написать SQL и не ебать себе мозг.
var query = @" WITH RankedOrders AS ( SELECT CustomerId, OrderDate, TotalAmount, ROW_NUMBER() OVER (PARTITION BY CustomerId ORDER BY OrderDate DESC) as rn FROM Orders ) SELECT * FROM RankedOrders WHERE rn = 1"; var lastOrders = await _context.Orders.FromSqlRaw(query).ToListAsync();Вот видишь? Красота же! Чисто, понятно, и база данных не обосрётся от кривого плана запроса.
-
Когда надо обновить или удалить овердохуища записей. Представь:
UPDATEна миллион строк. Загружать их все в память через EF, менять свойство и вызыватьSaveChangesAsync— это, прости, уровень долбоёба. Сервер памяти сожрёт и сдохнет. А так — хуяк одним запросом, и все дела.await _context.Database.ExecuteSqlInterpolatedAsync( $"UPDATE Products SET Price = Price * {1.1m} WHERE CategoryId = {categoryId}");Смотри, как аккуратно:
ExecuteSqlInterpolatedAsync. Параметры сами подставятся, SQL-инъекции не будет. Умно и быстро. -
Абсолютный контроль, когда терпения ноль ебать. Хочешь рулить подключением, читать данные потоком, как бог? Пожалуйста, на тебе старый добрый ADO.NET. Только не обосрись.
using (var connection = new SqlConnection(_config.GetConnectionString("Default"))) { await connection.OpenAsync(); var command = new SqlCommand("SELECT Id, Name FROM Users WHERE IsActive = @isActive", connection); command.Parameters.AddWithValue("@isActive", true); // СЛУШАЙ СЮДА, НЕ ХУЙ ЗАБЫВАТЬ! ВСЕГДА ПАРАМЕТРЫ! using (var reader = await command.ExecuteReaderAsync()) { while (await reader.ReadAsync()) { var id = reader.GetInt32(0); var name = reader.GetString(1); // ... ну и делай тут что хочешь } } }Видишь эту строку с параметрами? Это святое. Кто строки конкатенирует — тот пидарас шерстяной и его надо гнать из профессии поганой метлой.
И главное, запомни раз и нахуй: если уж полез в ручной SQL, то:
- ПАРАМЕТРИЗАЦИЯ. Я не шучу. Это не обсуждается.
- СМОТРИ ПЛАН ЗАПРОСА. А то напишешь какую-нибудь хуйню с
SELECT *иNOLOCKна всю таблицу, а потом удивляешься, почему всё встало колом. Будет тебе Хиросима, а не апдейт.
В общем, инструмент на все случаи жизни. Главное — мозги включать, а не просто копипастить с StackOverflow.