如何覆盖 SqlCommand 以抓取生成的 TSQL



有没有办法拦截SqlCommand生成的SQL?

我目前有一个将执行存储过程的方法:

public int ExecSP(string spName, params objec[] params)
{
using (SqlConnection con = new SqlConnection("AdventureWorks")) 
using (SqlCommand cmd = new SqlCommand(spName, con)) 
{
cmd.CommandType = CommandType.StoredProcedure;
//..calls method to add params and values to cmd object
con.Open();
return cmd.ExecuteNonQuery();
}
}

当我使用它来调用以下内容时:

ExecSP("HumanResources.uspUpdateEmployeePersonalInfo", 1, "295847284", new DateTime(1963, 3, 2), "S", "M");'

我在 SQLProfiler 中得到以下内容:

exec HumanResources.uspUpdateEmployeePersonalInfo @BusinessEntityID=1,@NationalIDNumber=N'295847284',@BirthDate='1963-03-02 00:00:00',@MaritalStatus=N'S',@Gender=N'M'

我想做的是拦截该SQL命令,以便我可以在其末尾添加一条注释,其中包含一些相关信息,使其看起来像:

exec HumanResources.uspUpdateEmployeePersonalInfo @BusinessEntityID=1,@NationalIDNumber=N'295847284',@BirthDate='1963-03-02 00:00:00',@MaritalStatus=N'S',@Gender=N'M' -- IMPORTANT INFORMATION HERE

我无法将 CommandType 更改为"文本",也无法向存储过程添加额外的参数。我试着看这些其他问题,但没有运气:

我可以覆盖 SqlCommand 函数吗?

SqlCommand to T-SQL

CommandType = CommandType.StoredProcedure的情况下,这是不可能的。

为什么?在 SQL 事件探查器中看到的 SQL 不是由客户端生成的。:-/

当 SqlCommand 执行CommandType.StoredProcedure命令时,它会向 SQL Server 发送一条执行远程过程调用消息,其中包含存储过程的名称和包含参数的数据结构。

RPC:Starting/RPC:Completed事件的 SQL 事件探查器显示TextData是在服务器端生成的。由于此文本不是在客户端生成的,因此无法在客户端对其进行修改。

您看到的是调试/配置文件消息,但这并不能完美地代表实际执行的内容(数据库将在幕后使用sp_executesql())。

您要查找的内容不存在。使用参数对象的全部意义在于,参数值在任何时候不能作为 sql 命令字符串的一部分包含在内,即使在服务器上也是如此

这主要完成了三件事:

  1. 它可以防止通过该查询进行 sql 注入攻击的任何可能性。你永远不会遇到一些奇怪的Unicode字符集问题,允许攻击者将命令插入到你的查询数据中,就像他们几年前使用php/mysql所做的那样,或者一些新的语言功能造成了你的旧转义代码不够好的情况。查询的用户数据部分在每个阶段始终与查询的命令逻辑部分分开。
  2. 它通过允许服务器缓存执行计划来提高性能。这样可以节省编译步骤,因为应用程序会一遍又一遍地执行可能相同的查询,只是使用不同的参数数据。
  3. 它避免了日期、带撇号的文本数据等内容的格式问题。

如果要获取调试数据,请编写一个方法来输出查询和随之而来的参数数据。如果要在配置文件跟踪中添加信息,可以切换到CommandType.Text并通过自己的EXEC procedurename @param1, @param2, ... @paramN -- INFO HERE字符串调用存储过程。

最新更新