是否有一种简单的方法来获取.NET为参数化查询生成的"sp_executesql"查询?

Sco*_*ain 5 .net c# sql .net-4.5

背景:

如果我有以下程序

public class Program
{
    public static void Main()
    {
        using(var connection = new SqlConnection("Server=(local);Database=Testing;Trusted_Connection=True"))
        using (var command = connection.CreateCommand())
        {
            connection.Open();
            command.CommandText = "UPDATE Foo set Bar = @Text";
            command.Parameters.Add("@Text", SqlDbType.VarChar, 50).Value = "Hello World!";
            command.ExecuteNonQuery();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

执行时,运行以下查询(根据SQL Server Profiler)

exec sp_executesql N'UPDATE Foo set Bar = @Text',N'@Text varchar(50)',@Text='Hello World!'
Run Code Online (Sandbox Code Playgroud)

我的问题:

我想要做的是,如果我有以下

command.CommandText = "UPDATE Foo set Bar = @Text";
command.Parameters.Add("@Text", SqlDbType.VarChar, 50).Value = "Hello World!";
string query = GenerateQuery(command);
Run Code Online (Sandbox Code Playgroud)

GenerateQuery 会返回字符串

"exec sp_executesql N'UPDATE Foo set Bar = @Text',N'@Text varchar(50)',@Text='Hello World!'"
Run Code Online (Sandbox Code Playgroud)

我能够编写一个遍历Parameters集合中每个参数并构建字符串的解析器.但是,在我从头开始编写这个解析器之前,.NET中是否有一些已经执行此操作的类或函数我忽略了?

如果我有权访问参数的MetaType,那么解析器将非常简单,但我不觉得在生产应用程序中使用反射来访问.NET框架的未发布的内部API.

Sol*_*zky 6

格雷戈里的回答有点正确,但大部分是不正确的。确实,没有public您可以调用的方法来获取此信息,但是有private一个(您无法调用)确实将CommandText和重新打包SqlParameterCollection为存储过程调用,sp_executesql并使用预先格式化的参数名称和数据类型列表作为该存储过程的第二个输入参数(请参阅BuildParamList下面的注释)。

虽然这是 Microsoft 源代码,但该代码也是开源 .NET Core 项目的一部分,该项目主要在MIT 许可发布。意思是,您可以复制和粘贴您需要的部分:-)。即使代码仅在 referencesource.microsoft.com 上,您仍然可以从中了解您需要的内容并使用它来验证您的版本在功能上是否与它一致。

看起来你需要的主要是BuildParamList方法(当然,不管它调用什么):