Приходилось ли писать низкоуровневые SQL-запросы напрямую к БД?

«Приходилось ли писать низкоуровневые SQL-запросы напрямую к БД?» — вопрос из категории Базы данных, который задают на 25% собеседований C# Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Да, в ряде сценариев работа с "сырым" SQL необходима, даже при использовании ORM вроде Entity Framework Core.

Типичные случаи и подходы:

  1. Сложные аналитические запросы: Операции, которые неэффективно или невозможно выразить через 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();
  2. Массовые операции (Bulk Operations): Для обновления/удаления большого объема данных ExecuteSqlRaw или ExecuteSqlInterpolated эффективнее, чем загрузка сущностей в память.

    await _context.Database.ExecuteSqlInterpolatedAsync(
        $"UPDATE Products SET Price = Price * {1.1m} WHERE CategoryId = {categoryId}");
  3. Работа с 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-инъекций и анализ плана выполнения для обеспечения эффективности.