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

How to override SqlCommand to grab generated 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 更改为 Text,也无法向存储过程添加额外的参数。我试着查看这些其他问题,但没有运气:

Can I override SqlCommand functions?

SqlCommand to T-SQL

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

为什么?您在 SQL Profiler 中看到的 SQL 不是由客户端生成的。 :-/

当 SqlCommand 执行 CommandType.StoredProcedure 命令时,它向 SQL 服务器发送一个带有存储过程名称和包含参数的数据结构的 execute remote procedure call message

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

您看到的是一条 debug/profile 消息,但这并不能完全代表实际执行的内容(数据库将在幕后使用 sp_executesql())。

您要查找的内容不存在。使用参数对象的全部意义在于参数值是 NEVER随时,作为 sql 命令字符串的一部分, 甚至在服务器上.

这主要完成了三件事:

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

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