升级到EFCore 3.1时,出现了过时的警告:
警告'RelationalDatabaseFacadeExtensions.ExecuteSqlCommandAsync(DatabaseFacade,CS0618 RawSqlString,params object[])“过时了:对于使用普通字符串的SQL查询的异步执行,使用ExecuteSqlRawAsync代替。对于使用内插字符串语法创建参数的SQL查询的异步执行,请使用ExecuteSqlInterpolatedAsync代替。” 警告'RelationalDatabaseFacadeExtensions.ExecuteSqlCommand(DatabaseFacade,CS0618 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);
参考精细手册,完全没有讨论典型的Server参数@somename
,实际上,我甚至不知道文档中的示例代码(在表名后面显示括号)是如何有效的SQL语法:
context.Database.ExecuteSqlRaw("SELECT * FROM [dbo].[SearchBlogs]({0})", userSuppliedSearchTerm)
我没有看到文档在哪里定义了userSuppliedSearchTerm
变量的内容或它的类型,而且我很难理解它是如何明智地成为SQL的核心(string userSuppliedSearchTerm = "WHERE id = 123";
中有烘焙值吗?)SQL注入?)或者一个原语值(int userSuppliedSearchTerm = 123
),这是否意味着它是某种自定义类型,指定了db列名和值?EFCore如何知道表中的哪一列将被查询?EFCore是否整理了括号所显示的语法错误?EFCore是否必须使用括号才能理解查询?
最后,我的问题是:考虑到我的ExecuteSqlCommand
代码是有意义的,而ExecuteSqlRaw
的文档没有什么意义/似乎解释得很糟糕,那么我们该如何从这个工作代码出发:
var id = 123;
context.Database.ExecuteSqlCommand("DELETE FROM Table WHERE ID = @p0", id);
使用ExecuteSqlRaw?
SomeType x = ???;
context.Database.ExecuteSqlRaw("???", x);
发布于 2020-01-09 16:27:05
我没有看到文档在哪里定义了userSuppliedSearchTerm变量的内容或它的类型,而且我很难理解它是如何明智地成为SQL的核心(string userSuppliedSearchTerm = "WHERE = 123";使用烘焙值吗?SQL注入?)或者一个原语值(int userSuppliedSearchTerm = 123),这是否意味着它是某种自定义类型,指定了db列名和值?EFCore如何知道表中的哪一列将被查询?EFCore是否整理了括号所显示的语法错误?EFCore是否必须使用括号才能理解查询?
与EF核心无关
文档选择使用一个表值函数dbo.SearchBlogs
来演示原始SQL查询的用法,因此SELECT * FROM [dbo].[SearchBlogs]({0})
是合法的SearchBlogs
,因为SearchBlogs
是一个函数,而不是一个表/视图--只是在我链接的文档中没有提到它。
发布于 2020-01-09 16:05:48
规则很简单。
EFCore2.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
参数的原因是v2.x重载#1和#3的C#编译时重载解析。有时,当打算使用另一个重载时,它选择插值,反之亦然。有单独的名字可以清楚地表明意图。
您可以阅读更多关于EFCore3.0ClingChange- FromSql、ExecuteSql和ExecuteSqlAsync已被重命名中的推理的文章。
有关受支持的参数占位符、名称和值的信息可以在原始SQL查询-传递参数中找到。
但是要回答您的具体问题,如果现有的v2.x代码是
context.Database.ExecuteSqlCommand("DELETE FROM Table WHERE ID = @p0", id);
然后将其更改为ExecuteSqlRaw
。
如果是
context.Database.ExecuteSqlCommand($"DELETE FROM Table WHERE ID = {id}");
然后将其更改为ExecuteSqlInterpolated
。
https://stackoverflow.com/questions/59662673
复制相似问题