EF 核心上下文.Database.ExecuteSqlRaw(sql, param1, param2) 抛出 SqlE



ef 我使用的核心版本是:3.0 我写的代码有点像下面这样:

SqlParameter table = new SqlParameter("@tableName", tableName);
SqlParameter entryId = new SqlParameter("@entryId", id);
string sql = "delete from @tableName where id = @entryId";
context.Database.ExecuteSqlRaw(sql, table , entryId);

我的SQL语句有两个参数,我已经定义并传递了,但是每次执行它时,我都得到了以下异常,请帮忙看看。

谢谢

Microsoft.Data.SqlClient.SqlException (0x80131904(:必须声明 表变量"@tableName"。 在 Microsoft.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action1 wrapCloseInAction) at Microsoft.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action1 wrapCloseInAction( at Microsoft.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose( at Microsoft.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean&dataReady( at Microsoft.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, 运行行为 运行行为, 字符串重置选项字符串, 布尔值 isInternal, Boolean forDescribeParameterEncryption, Boolean shouldCacheForAlwaysEncrypted( at Microsoft.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean isAsync, Int32 timeout, Task& task, Boolean asyncWrite, Boolean inRetry, SqlDataReader ds, Boolean describeParameterEncryptionRequest( 在 Microsoft.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, 任务完成源1 completion, Int32 timeout, Task& task, Boolean& usedCache, Boolean asyncWrite, Boolean inRetry, String method) at Microsoft.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource1 completion, boolean sendToPipe, Int32 timeout, Boolean& usedCache, Boolean asyncWrite, Boolean inRetry, String methodName( at Microsoft.Data.SqlClient.SqlCommand.ExecuteNonQuery(( at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteNonQuery(RelationalCommandParameterObject 参数对象( at Microsoft.EntityFrameworkCore.RelationalDatabaseFacadeExtensions.ExecuteSqlRaw(DatabaseFacade databaseFacade, String sql, IEnumerable'1 parameters( at Microsoft.EntityFrameworkCore.RelationalDatabaseFacadeExtensions.ExecuteSqlRaw(DatabaseFacade databaseFacade, String sql, Object[] parameters( at

表名和列名不能参数化。在 C# 术语中,这就像将类名放在字符串中并尝试实例化它:

string className = "Person";
className p = new className; //it doesn't work

您的代码必须更像:

SqlParameter entryId = new SqlParameter("@entryId", id);
string sql = "delete from "+tableName+" where id = @entryId";
context.Database.ExecuteSqlRaw(sql, entryId);

不要让最终用户能够更改 tableName 变量的内容


额外信息由Lutti Coelho提供:

若要避免查询中的 SQL 注入,最好使用ExecuteSqlInterpolated方法。此方法允许以防止 SQL 注入攻击的方式使用字符串内插语法。

context.Database.ExecuteSqlInterpolated("delete from {tableName} where id = {id}");

始终对原始 SQL 查询使用参数化

在原始 SQL 查询中引入任何用户提供的值时,必须注意避免 SQL 注入攻击。除了验证此类值不包含无效字符外,请始终使用参数化,该参数化将值与 SQL 文本分开发送。

特别是,切勿将带有未经验证的用户提供值的串联或内插字符串 ($"( 传递到 FromSqlRaw 或 ExecuteSqlRaw。FromSqlInterpolated 和 ExecuteSqlInterpolated 方法允许使用字符串内插语法,以防止 SQL 注入攻击。

您可以在此链接中查看有关原始 SQL 查询的更多信息: https://learn.microsoft.com/en-us/ef/core/querying/raw-sql

相关内容

最新更新