Являются ли EF Core 3.1 ExecuteSqlRaw / ExecuteSqlRawAsyn c заменой для ExecuteSqlCommand / ExecuteSqlCommandAsyn c? - PullRequest
4 голосов
/ 09 января 2020

При обновлении до EFCore 3.1 появились устаревшие предупреждения:

Предупреждение CS0618 'RelationalDatabaseFacadeExtensions.ExecuteSqlCommandAsyn c (DatabaseFacade, RawSqlString, params object [])' устарел: 'Для асинхронной передачи c выполнение SQL запросов с использованием простых строк, вместо этого используйте ExecuteSqlRawAsyn c. Для асинхронного c выполнения SQL запросов с использованием синтаксиса интерполированной строки для создания параметров используйте вместо этого ExecuteSqlInterpolatedAsyn c. '

Warning CS0618' RelationalDatabaseFacadeExtensions.ExecuteSqlCommand (DatabaseFacade, RawSqlString, params object]] 'устарел:' Для выполнения SQL запросов с использованием простых строк используйте вместо него ExecuteSqlRaw. Для выполнения SQL запросов с использованием интерполированного строкового синтаксиса для создания параметров используйте вместо этого ExecuteSqlInterpolated. '

Старый код, к которому они относятся, выглядит следующим образом:

context.Database.ExecuteSqlCommand("DELETE FROM Table WHERE ID = @p0", id);
await context.Database.ExecuteSqlCommandAsync("DELETE FROM Table2 WHERE ID = @p0", id);

Консалтинг прекрасное руководство , типичные SQL Параметры сервера @somename вообще не обсуждаются, и на самом деле я даже не вижу, как пример кода в документах, где они показывают открытие скобок после допустимо имя таблицы SQL синтаксис:

context.Database.ExecuteSqlRaw("SELECT * FROM [dbo].[SearchBlogs]({0})", userSuppliedSearchTerm)

Я не видел, где документы определяют содержимое переменной userSuppliedSearchTerm или ее тип, и я изо всех сил пытаюсь понять, как это может быть разумный слепок SQL (string userSuppliedSearchTerm = "WHERE id = 123"; с запеченными в значениях? SQL Injection?) или одиночное примитивное значение (int userSuppliedSearchTerm = 123), так что это означает, что это какой-то пользовательский тип, который задает столбец db имя и значение? Как EFCore узнает, какой столбец из таблицы следует запрашивать? Разбирает ли EFCore синтаксическую ошибку, представленную в скобках? Обязательны ли для EFCore круглые скобки, чтобы понять запрос?

В конечном счете, мой вопрос: учитывая, что мой код ExecuteSqlCommand имеет смысл, а документы для ExecuteSqlRaw не имеют смысла / кажутся плохо объясненными, как мы go из этого рабочего кода:

var id = 123;
context.Database.ExecuteSqlCommand("DELETE FROM Table WHERE ID = @p0", id);

Для использования ExecuteSqlRaw?

SomeType x = ???;
context.Database.ExecuteSqlRaw("???", x);

Ответы [ 2 ]

7 голосов
/ 09 января 2020

Правило простое.

EF Core 2.x имеет 3 ExecuteSqlCommand перегрузки:

public static int ExecuteSqlCommand(this DatabaseFacade databaseFacade,
    RawSqlString sql, params object[] parameters); // 1
public static int ExecuteSqlCommand(this DatabaseFacade databaseFacade,
   RawSqlString sql, IEnumerable<object> parameters); // 2
public static int ExecuteSqlCommand(this DatabaseFacade databaseFacade,
    FormattableString sql); // 3

, которые в EF Core 3.x отображаются на

public static int ExecuteSqlRaw(this DatabaseFacade databaseFacade,
    string sql, params object[] parameters); // 1
public static int ExecuteSqlRaw(this DatabaseFacade databaseFacade,
    string sql, IEnumerable<object> parameters); // 2
public static int ExecuteSqlInterpolated(this DatabaseFacade databaseFacade,
    FormattableString sql); // 3

Функционально они полностью эквивалентны. Перегрузки Raw поддерживают те же метки-заполнители и значения параметров (как именованные, так и неназванные), что и перегрузки v2.x # 1 и # 2. И Interpolated ведет себя точно так же, как и перегрузка v2.x № 3.

Причиной переименования метода и использования разных имен для интерполированного и не интерполированного параметра sql является время компиляции C#. разрешение перегрузки для v2.x перегрузок # 1 и # 3. Иногда он выбирает интерполированный, когда намеревался использовать другой, и наоборот. Наличие отдельных имен проясняет намерение.

Подробнее об аргументации вы можете прочитать в EF Core 3.0 Срочные изменения - С Sql, Выполнить Sql и ВыполнениеSqlAsyn c переименованы .

Информация о поддерживаемых параметрах-заполнителях, именах и значениях может быть найдена в необработанных SQL запросах - передача параметров .

Но для ответа на ваш конкретный вопрос, если существующий код v2.x это

context.Database.ExecuteSqlCommand("DELETE FROM Table WHERE ID = @p0", id);

, затем измените его на ExecuteSqlRaw.

А если было

context.Database.ExecuteSqlCommand($"DELETE FROM Table WHERE ID = {id}");

, то измените его на ExecuteSqlInterpolated.

0 голосов
/ 09 января 2020

Я не видел, где документы когда-либо определяют содержимое переменной userSuppliedSearchTerm или ее тип, и я изо всех сил пытаюсь понять, как это может быть осмысленно слепок SQL (строка userSuppliedSearchTerm = "WHERE id = 123 "; с запеченными в значениях? SQL Injection?) или одиночное примитивное значение (int userSuppliedSearchTerm = 123), значит ли это, что это какой-то пользовательский тип, который задает имя столбца БД и значение? Как EFCore узнает, какой столбец из таблицы следует запрашивать? Разбирает ли EFCore синтаксическую ошибку, представленную в скобках? Обязательны ли в EFCore круглые скобки для понимания запроса?

Все это никак не связано с EF Core

В документах выбрано использование табличной функции dbo.SearchBlogs для демонстрации использования необработанных SQL запросов, поэтому SELECT * FROM [dbo].[SearchBlogs]({0}) допустимо SQL, потому что SearchBlogs является функцией, а не таблицей / представлением - это просто не упоминалось в документах, которые я связал

...