Solución:
La regla es simple.
EF Core 2.x tiene 3 ExecuteSqlCommand
sobrecargas:
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
que en EF Core 3.x se asignan a
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
Funcionalmente son completamente equivalentes. Raw
overloads admite los mismos marcadores de posición y valores de parámetro (tanto con nombre como sin nombre) que las sobrecargas v2.x # 1 y # 2. Y Interpolated
tiene exactamente el mismo comportamiento que la sobrecarga v2.x # 3.
La razón para cambiar el nombre del método y usar nombres diferentes para interpolados y no interpolados sql
El parámetro es la resolución de sobrecarga de tiempo de compilación de C # para las sobrecargas n. ° 1 y n. ° 3 de v2.x. A veces elige interpolar cuando la intención era utilizar el otro, y viceversa. Tener nombres separados deja clara la intención.
Puede leer más sobre el razonamiento en EF Core 3.0 Cambios importantes: se ha cambiado el nombre de FromSql, ExecuteSql y ExecuteSqlAsync.
La información sobre los marcadores de posición, nombres y valores de los parámetros admitidos se puede encontrar en Consultas SQL sin formato: Pasar parámetros.
Pero para responder a su pregunta concreta, si el código v2.x existente es
context.Database.ExecuteSqlCommand("DELETE FROM Table WHERE ID = @p0", id);
luego cámbialo a ExecuteSqlRaw
.
Y si fuera
context.Database.ExecuteSqlCommand($"DELETE FROM Table WHERE ID = {id}");
luego cámbialo a ExecuteSqlInterpolated
.
No vi dónde los documentos definen el contenido de la variable userSuppliedSearchTerm o su tipo, y estoy luchando por ver cómo podría ser sensiblemente una pepita de SQL (string userSuppliedSearchTerm = “WHERE id = 123”; con horneado en ¿valores? ¿Inyección SQL?) o un único valor primitivo (int userSuppliedSearchTerm = 123) ¿significa que es algún tipo de tipo personalizado que especifica el nombre de la columna db y el valor? ¿Cómo sabe EFCore qué columna de la tabla se va a consultar? ¿EFCore soluciona el error de sintaxis presentado por los paréntesis? ¿Los paréntesis son obligatorios para que EFCore comprenda la consulta?
Todo nada que ver con EF Core
Los documentos han optado por utilizar una función con valores de tabla dbo.SearchBlogs
para demostrar el uso de consultas SQL sin procesar, por lo que SELECT * FROM [dbo].[SearchBlogs]({0})
es SQL legal porque SearchBlogs
es una función, no una tabla / vista, simplemente no se mencionó en los documentos que vinculé