一尘不染

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

sql

背景:

如果我有以下程序

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();
        }
    }
}

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

exec sp_executesql N'UPDATE Foo set Bar = @Text',N'@Text varchar(50)',@Text='Hello World!'

我的问题:

我想做的是,如果我有以下情况

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

GenerateQuery 将返回字符串

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

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

如果我可以访问编写该解析器的参数的MetaType,将非常容易,但是使用生产应用程序中的反射来访问.NET框架的未发布内部API时,我觉得不值得。


阅读 115

收藏
2021-05-23

共1个答案

一尘不染

格雷戈里的答案是正确的,但大多数都是错误的。没错,没有public可以调用的方法,但是有private一个(您不能调用)确实可以重新打包CommandTextSqlParameterCollection作为存储过程调用的方法,sp_executesql并以预先格式化的参数名和数据类型列表作为参数。该存储过程的第二个输入参数(请参阅BuildParamList下面的注释)。

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

  • Microsoft.com上的原始代码,位于:http : //referencesource.microsoft.com/#System.Data/System/Data/SqlClient/SqlCommand.cs,5400
  • GitHub.net上的.NET Core版本,网址为:https : //github.com/dotnet/corefx/blob/master/src/System.Data.SqlClient/src/System/Data/SqlClient/SqlCommand.cs#L2820

似乎您需要的主要是BuildParamList方法(当然,无论它叫什么):

2021-05-23