Строковая интерполяция внутри форматируемой строки в C#

Я заменяю Dapper на EF Core в проекте. В частности, используя новые функции Database.SqlQuery и Database.ExecuteSql с EF Core. Мне нравится, как они используют FormattableString для обработки параметров SQL.

Однако я не понимаю, что делать, если я хочу использовать как интерполяцию строк, так и фигурные скобки для параметров с помощью FormattableStrings? Ниже приведен пример версии Dapper и нерабочей версии EF Core. Я бы не хотел, чтобы «subSql» передавался в качестве параметра, а просто создавал строку. Как бы я подошел к этому?

public IEnumerable<Something> GetSomethingWithDapper(string id, bool enabled, string type)
{
    var subSql = switch (type) {
        case "A":
            "TableA";
            break;
        case "B":
            "TableB";
            break;
    };
    
    var sql = $"SELECT * FROM {subSql} WHERE Id = @id";
    
    // My dapper request here
}

public IEnumerable<Something> GetSomethingWithEFCore(string id, string type)
{
    var subSql = switch (type) {
        case "A":
            "TableA";
            break;
        case "B":
            "TableB";
            break;
    };
    
    FormattableString sql = $"SELECT * FROM {subSql} WHERE Id = {id}";
    
    // My EF Core request here
}

Если вы используете EF Core, почему вы вообще используете необработанный SQL? EF Core — это ORM, а не драйвер базы данных. Он пытается создать впечатление работы с объектами в памяти, а не с таблицами и строками. Задача EF — генерировать запросы на основе сущностей и их отношений, а не ваша. Вместо этого кода все, что вам действительно нужно, это var customer=context.Customers.Find(id);. А если вам нужны заказы клиента, var customer=context.Customers.Include(c=>c.Orders).Find(id);

Panagiotis Kanavos 04.07.2024 09:38

Мы используем как Dapper, так и EF Core. Действуйте только тогда, когда нам нужно получить данные, которые не являются просто представлением моделей. Эти части я хотел бы заменить сейчас, поскольку EF Core поддерживает это.

Samuel Wahlberg 04.07.2024 09:41

Почему бы не добавить его в модель? И зачем отходить от Дэппера? Support и Is Better не одно и то же. Очевидно, вы отображаете всю таблицу, так почему же Something не является частью модели?

Panagiotis Kanavos 04.07.2024 09:43

Это ответ на ваш вопрос?: stackoverflow.com/a/50452479/25070013

Peko Miko 04.07.2024 09:46

@PekoMiko Нет, я вообще ничего не вижу в этом ответе о строгой интерполяции?

Samuel Wahlberg 04.07.2024 09:50

@PanagiotisKanavos Я полагаю, вы понимаете, что мой пример не является реальным случаем, а только отражает проблему с интерполяцией строк? Я не думаю, что вам нужно чрезмерно анализировать структуру модели в этом примере. Сегодня мы используем 90% EF Core и 10% Dapper. Мы просто хотели бы заменить последние 10%, которые у нас есть, на Dapper, поскольку раньше это было невозможно сделать в EF Core. Я большой поклонник Dapper, но хотел бы уменьшить количество необходимых пакетов. Я прекрасно осведомлен о сильных сторонах пакета, поэтому вам не придется меня убеждать :)

Samuel Wahlberg 04.07.2024 09:54

Вы изначально задаете неправильный вопрос. Вы пытаетесь использовать интерполяцию для двух разных целей: создания параметризованного запроса и построения строки запроса. Это просто не сработает. Вам придется создать строку "SELECT * FROM TableA WHERE Id = {id}", прежде чем создавать FormattableString, которая ожидает параметр id.

Panagiotis Kanavos 04.07.2024 09:54

@PanagiotisKanavos Отлично! Это именно то, о чем я прошу. Как мне следует это сделать! Как бы я это сделал?

Samuel Wahlberg 04.07.2024 09:56

Эквивалент Dapper в любом случае не использует форматируемые строки, это FromSqlRaw. Вы можете написать FromSqlRaw(sql,id) так же, как вы это сделали с Dapper. И я по-прежнему предпочитаю Dapper для этого, потому что, хотя Марк Гравелл сейчас работает в Microsoft, Dapper более зрелый, в то время как команда EF Core выпустила эту функцию всего пару лет назад. У Dapper уже есть версия, которая поддерживает встроенную компиляцию, а EF Core — нет.

Panagiotis Kanavos 04.07.2024 09:59

Итак, реальный вопрос заключается в том, как избежать фигурных скобок при интерполяции строк?.... Используйте двойные фигурные скобки...

Selvin 04.07.2024 10:04

@Селвин, нет, это не так. В форматируемой строке нет экранированных параметров. Что-то является либо текстом, либо параметром. FromSql рассматривает все параметры в форматируемой строке как параметры запроса. Нельзя сказать, что половина параметров должна использоваться для интерполяции строк, а половина — для параметров запроса.

Panagiotis Kanavos 04.07.2024 10:07
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
11
83
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Эквивалентом QueryAsync<Something>(sql,id) Dapper является SqlQueryRaw, а не SqlQuery или FromSql. SqlQuery и FromSql будут обрабатывать все параметры в FormattableString как параметры запроса. Невозможно определить, что некоторые из этих параметров следует использовать для интерполяции строк, а некоторые — для других целей.

При использовании SqlQueryRaw эквивалентом con.Query<int>(sql,new {id}) Dapper является context.Database.SqlQueryRaw<int>(sql,new{id}), например:

var id= new SqlParameter("id", 45);
var ids = context.Database
    .SqlQueryRaw<int>("SELECT Id from TableX where id=@id",@id)
    .ToList();

Или

var sql=$"SELECT Id from {table} where id=@id";
var ids = context.Database
    .SqlQueryRaw<int>("SELECT Id from TableX where id=@id",id)
    .ToList();

Это также показано в документации EF SQL-запрос , в разделе Динамический SQL и параметры:

Если вы решили, что хотите динамически создавать свой SQL, вам придется использовать FromSqlRaw, который позволяет интерполировать переменные данные непосредственно в строку SQL вместо использования параметра базы данных:

var columnName = "Url";
var columnValue = new SqlParameter("columnValue", "http://SomeURL");

var blogs = context.Blogs
    .FromSqlRaw($"SELECT * FROM [Blogs] WHERE {columnName} = @columnValue", columnValue)
    .ToList();

Другие вопросы по теме