如何重写SqlCommand以获取生成的TSQL

时间:2017-03-28 21:20:40

标签: c# sql-server ado.net sqlcommand sqlprofiler

有没有办法拦截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&#34);`

我在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

2 个答案:

答案 0 :(得分:1)

如果是CommandType = CommandType.StoredProcedure,则无法做到这一点。

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

当SqlCommand执行CommandType.StoredProcedure命令时,它会向SQL Server发送一个execute remote procedure call message,其中包含存储过程的名称和包含这些参数的数据结构。

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

答案 1 :(得分:0)

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

您所寻找的内容并不存在。使用参数对象的重点是参数值 NEVER 随时,作为sql命令字符串的一部分包含在内,甚至在服务器上

这完成了三件主要的事情:

  1. 它可以防止通过该查询进行sql注入攻击的任何可能性。您永远不会出现一些奇怪的unicode字符集问题,允许攻击者在您的查询数据中插入命令,例如they did a couple years back with php/mysql,或创建一些新的语言功能你的旧逃脱代码不够好的情况。在每个阶段,查询的用户数据部分始终与查询的命令逻辑部分分开。
  2. 通过允许服务器缓存执行计划来提高性能。这样可以节省编译步骤,因为您的应用程序可以反复执行同一个查询,只需使用不同的参数数据。
  3. 避免了日期,带撇号的文本数据等格式化问题。
  4. 如果要获取调试数据,请编写一个方法来输出查询以及随之而来的参数数据。如果要在配置文件跟踪中添加信息,可以切换到CommandType.Text并通过自己的EXEC procedurename @param1, @param2, ... @paramN -- INFO HERE字符串调用存储过程。