从一个SqlCommand对象中获取生成的SQL语句?

220

我有以下代码:

Using cmd As SqlCommand = Connection.CreateCommand
    cmd.CommandText = "UPDATE someTable SET Value = @Value"
    cmd.CommandText &= " WHERE Id = @Id"
    cmd.Parameters.AddWithValue("@Id", 1234)
    cmd.Parameters.AddWithValue("@Value", "myValue")
    cmd.ExecuteNonQuery
End Using

我想知道是否有办法将最终生成的SQL语句作为字符串获取,它应该类似于这样:

UPDATE someTable SET Value = "myValue" WHERE Id = 1234

如果有人想知道为什么我要这样做:

  • 用于记录(失败的)语句
  • 为了能够将其复制并粘贴到企业管理器中进行测试

1
如果不区分不同的数据类型、SQL注入、参数名称相似(替换问题)等情况,为什么你会标记答案 https://dev59.com/QXVC5IYBdhLWcg3wihmv#265261 呢? - Kiquenet
@Kiquenet 我本来以为我试过了,但它没让我这么做。现在它可以了。谢谢你。 - dummy
1
如果你想准确生成将要运行的SQL,请查看TdsParser.TdsExecuteRPC(https://github.com/Microsoft/referencesource/blob/master/System.Data/System/Data/SqlClient/TdsParser.cs),但也要有点害怕。 - Rory
25个回答

149

为了记录日志,恐怕没有更好的方法,只能自己构建字符串:

string query = cmd.CommandText;

foreach (SqlParameter p in cmd.Parameters)
{
    query = query.Replace(p.ParameterName, p.Value.ToString());
}

2
虚拟的:不完全如此。如果您执行预处理语句,您会面临 SQL 注入攻击的风险。对答案加1。 - Sunny Milenov
14
这里需要注意一个问题。如果我有“Param”和“differentParam”作为参数,它会使得“differentParam”变得无用,因为它会被替换成“ValueParam”,假设“Param=Value”。 - Alok
5
该问题不涉及防御性编程技术,因此空引用检查不是答案的组成部分。它应该被实现的事实是暗示的,因此我认为这不是一个建设性的评论。 - Kon
@Kon添加了您答案的修改版本。Handles参数名称相似,而Replace只是将它们分开。 - HouseCat
4
消除@Alok指出的参数名称相似问题的一种稍微更好的方法可能是使用query = Regex.Replace(query, @"\b" + p.ParameterName + @"\b", p.Value.ToString());来替换字符串中的参数。这将替换“整个单词”。尽管如此,它可能不是一个通用的解决方案,因为\b标记表示单词字符和非单词字符之间的位置,所以如果您的参数名称以@开头,则应使用p.ParameterName + @"\b"来替换查询字符串中的参数。 - stambikk
显示剩余6条评论

132

虽然不完美,但我为TSQL准备了一些东西 - 可以轻松地调整其他类型... 如果没有其他问题,它将为您提供自己改进的起点 :)

这对于数据类型和输出参数等类似于在SSMS中使用“执行存储过程”的操作做得还可以。我们大多数时候使用SPs,因此“text”命令不考虑参数等。

    public static String ParameterValueForSQL(this SqlParameter sp)
    {
        String retval = "";

        switch (sp.SqlDbType)
        {
            case SqlDbType.Char:
            case SqlDbType.NChar:
            case SqlDbType.NText:
            case SqlDbType.NVarChar:
            case SqlDbType.Text:
            case SqlDbType.Time:
            case SqlDbType.VarChar:
            case SqlDbType.Xml:
            case SqlDbType.Date:
            case SqlDbType.DateTime:
            case SqlDbType.DateTime2:
            case SqlDbType.DateTimeOffset:
                retval = "'" + sp.Value.ToString().Replace("'", "''") + "'";
                break;

            case SqlDbType.Bit:
                retval = (sp.Value.ToBooleanOrDefault(false)) ? "1" : "0";
                break;

            default:
                retval = sp.Value.ToString().Replace("'", "''");
                break;
        }

        return retval;
    }

    public static String CommandAsSql(this SqlCommand sc)
    {
        StringBuilder sql = new StringBuilder();
        Boolean FirstParam = true;

        sql.AppendLine("use " + sc.Connection.Database + ";");
        switch (sc.CommandType)
        {
            case CommandType.StoredProcedure:
                sql.AppendLine("declare @return_value int;");

                foreach (SqlParameter sp in sc.Parameters)
                {
                    if ((sp.Direction == ParameterDirection.InputOutput) || (sp.Direction == ParameterDirection.Output))
                    {
                        sql.Append("declare " + sp.ParameterName + "\t" + sp.SqlDbType.ToString() + "\t= ");

                        sql.AppendLine(((sp.Direction == ParameterDirection.Output) ? "null" : sp.ParameterValueForSQL()) + ";");

                    }
                }

                sql.AppendLine("exec [" + sc.CommandText + "]");

                foreach (SqlParameter sp in sc.Parameters)
                {
                    if (sp.Direction != ParameterDirection.ReturnValue)
                    {
                        sql.Append((FirstParam) ? "\t" : "\t, ");

                        if (FirstParam) FirstParam = false;

                        if (sp.Direction == ParameterDirection.Input)
                            sql.AppendLine(sp.ParameterName + " = " + sp.ParameterValueForSQL());
                        else

                            sql.AppendLine(sp.ParameterName + " = " + sp.ParameterName + " output");
                    }
                }
                sql.AppendLine(";");

                sql.AppendLine("select 'Return Value' = convert(varchar, @return_value);");

                foreach (SqlParameter sp in sc.Parameters)
                {
                    if ((sp.Direction == ParameterDirection.InputOutput) || (sp.Direction == ParameterDirection.Output))
                    {
                        sql.AppendLine("select '" + sp.ParameterName + "' = convert(varchar, " + sp.ParameterName + ");");
                    }
                }
                break;
            case CommandType.Text:
                sql.AppendLine(sc.CommandText);
                break;
        }

        return sql.ToString();
    }

这将生成类似以下内容的输出...

use dbMyDatabase;
declare @return_value int;
declare @OutTotalRows   BigInt  = null;
exec [spMyStoredProc]
    @InEmployeeID = 1000686
    , @InPageSize = 20
    , @InPage = 1
    , @OutTotalRows = @OutTotalRows output
;
select 'Return Value' = convert(varchar, @return_value);
select '@OutTotalRows' = convert(varchar, @OutTotalRows);

11
做得不错,实际上尝试着解决问题,单凭努力就赞成了。 - Adam Tolley
3
你的 "ToBooleanOrDefault(false)" 方法会是什么? - Benoittr
7
@Benoittr,你可以在这里看到ToBooleanOrDefault的实现:问题#3244850 - Alexandre Marcondes
2
进行了一些微小的调整并添加了表值参数。它已经发布在 GitHub 上,还有一个 .Net Standard 2.0 Nuget 包 https://github.com/jphellemons/CommandAsSql。感谢 Flapper!我能把你加为合作者吗? - JP Hellemons
1
值得注意的是,文本命令可以(而且应该)接受参数,而不仅仅是存储过程。 - apc
显示剩余7条评论

59

你不能这样做,因为它不会生成任何SQL。

参数化查询(CommandText中的查询)将作为预处理语句发送到SQL Server。当您执行该命令时,参数和查询文本是分开处理的。在任何时候都不会生成完整的SQL字符串。

您可以使用SQL Profiler来查看背后的情况。


12
SQL已经生成 - 在Profiler中查看 - 那就是我想要用于日志记录目的的文本。 - kpkpkp
除了 SQL Profiler(如果我正确理解了一些微软的评论,它正在被新的 SQL Server 废弃),根据其他答案,还可以使用 Activity Monitor。 - George Birbilis

38

我需要一个类似的命令字符串转换器,以便进行更详细的日志记录,因此我编写了这个工具。它将生成重新执行命令所需的文本,包括输出参数和结构化参数,在新会话中使用。它经过轻微测试,但请自行决定是否使用。

示例:

SqlCommand cmd = new SqlCommand("GetEntity", con);
cmd.Parameters.AddWithValue("@foobar", 1);
cmd.Parameters.Add(new SqlParameter(){
    ParameterName = "@outParam",
    Direction = ParameterDirection.Output,
    SqlDbType = System.Data.SqlDbType.Int
});
cmd.Parameters.Add(new SqlParameter(){
    Direction = ParameterDirection.ReturnValue
});
cmd.CommandType = CommandType.StoredProcedure;

将会产生:

-- BEGIN COMMAND
DECLARE @foobar INT = 1;
DECLARE @outParam INT = NULL;
DECLARE @returnValue INT;
-- END PARAMS
EXEC @returnValue = GetEntity @foobar = @foobar, @outParam = @outParam OUTPUT
-- RESULTS
SELECT 1 as Executed, @returnValue as ReturnValue, @outParam as [@outParam];
-- END COMMAND

实现:

public class SqlCommandDumper
{
    public static string GetCommandText(SqlCommand sqc)
    {
        StringBuilder sbCommandText = new StringBuilder();

        sbCommandText.AppendLine("-- BEGIN COMMAND");

        // params
        for (int i = 0; i < sqc.Parameters.Count; i++)
            logParameterToSqlBatch(sqc.Parameters[i], sbCommandText);
        sbCommandText.AppendLine("-- END PARAMS");

        // command
        if (sqc.CommandType == CommandType.StoredProcedure)
        {
            sbCommandText.Append("EXEC ");

            bool hasReturnValue = false;
            for (int i = 0; i < sqc.Parameters.Count; i++)
            {
                if (sqc.Parameters[i].Direction == ParameterDirection.ReturnValue)
                    hasReturnValue = true;
            }
            if (hasReturnValue)
            {
                sbCommandText.Append("@returnValue = ");
            }

            sbCommandText.Append(sqc.CommandText);

            bool hasPrev = false;
            for (int i = 0; i < sqc.Parameters.Count; i++)
            {
                var cParam = sqc.Parameters[i];
                if (cParam.Direction != ParameterDirection.ReturnValue)
                {
                    if (hasPrev)
                        sbCommandText.Append(",");
                    sbCommandText.Append(" ");

                    sbCommandText.Append(cParam.ParameterName);
                    sbCommandText.Append(" = ");
                    sbCommandText.Append(cParam.ParameterName);

                    if (cParam.Direction.HasFlag(ParameterDirection.Output))
                        sbCommandText.Append(" OUTPUT");

                    hasPrev = true;
                }
            }
        }
        else
        {
            sbCommandText.AppendLine(sqc.CommandText);
        }

        sbCommandText.AppendLine("-- RESULTS");
        sbCommandText.Append("SELECT 1 as Executed");
        for (int i = 0; i < sqc.Parameters.Count; i++)
        {
            var cParam = sqc.Parameters[i];

            if (cParam.Direction == ParameterDirection.ReturnValue)
            {
                sbCommandText.Append(", @returnValue as ReturnValue");
            }
            else if (cParam.Direction.HasFlag(ParameterDirection.Output))
            {
                sbCommandText.Append(", ");
                sbCommandText.Append(cParam.ParameterName);
                sbCommandText.Append(" as [");
                sbCommandText.Append(cParam.ParameterName);
                sbCommandText.Append(']');
            }
        }
        sbCommandText.AppendLine(";");

        sbCommandText.AppendLine("-- END COMMAND");
        return sbCommandText.ToString();
    }

    private static void logParameterToSqlBatch(SqlParameter param, StringBuilder sbCommandText)
    {
        sbCommandText.Append("DECLARE ");
        if (param.Direction == ParameterDirection.ReturnValue)
        {
            sbCommandText.AppendLine("@returnValue INT;");
        }
        else
        {
            sbCommandText.Append(param.ParameterName);

            sbCommandText.Append(' ');
            if (param.SqlDbType != SqlDbType.Structured)
            {
                logParameterType(param, sbCommandText);
                sbCommandText.Append(" = ");
                logQuotedParameterValue(param.Value, sbCommandText);

                sbCommandText.AppendLine(";");
            }
            else
            {
                logStructuredParameter(param, sbCommandText);
            }
        }
    }

    private static void logStructuredParameter(SqlParameter param, StringBuilder sbCommandText)
    {
        sbCommandText.AppendLine(" {List Type};");
        var dataTable = (DataTable)param.Value;

        for (int rowNo = 0; rowNo < dataTable.Rows.Count; rowNo++)
        {
            sbCommandText.Append("INSERT INTO ");
            sbCommandText.Append(param.ParameterName);
            sbCommandText.Append(" VALUES (");

            bool hasPrev = false;
            for (int colNo = 0; colNo < dataTable.Columns.Count; colNo++)
            {
                if (hasPrev)
                {
                    sbCommandText.Append(", ");
                }
                logQuotedParameterValue(dataTable.Rows[rowNo].ItemArray[colNo], sbCommandText);
                hasPrev = true;
            }
            sbCommandText.AppendLine(");");
        }
    }

    const string DATETIME_FORMAT_ROUNDTRIP = "o";
    private static void logQuotedParameterValue(object value, StringBuilder sbCommandText)
    {
        try
        {
            if (value == null)
            {
                sbCommandText.Append("NULL");
            }
            else
            {
                value = unboxNullable(value);

                if (value is string
                    || value is char
                    || value is char[]
                    || value is System.Xml.Linq.XElement
                    || value is System.Xml.Linq.XDocument)
                {
                    sbCommandText.Append("N'");
                    sbCommandText.Append(value.ToString().Replace("'", "''"));
                    sbCommandText.Append('\'');
                }
                else if (value is bool)
                {
                    // True -> 1, False -> 0
                    sbCommandText.Append(Convert.ToInt32(value));
                }
                else if (value is sbyte
                    || value is byte
                    || value is short
                    || value is ushort
                    || value is int
                    || value is uint
                    || value is long
                    || value is ulong
                    || value is float
                    || value is double
                    || value is decimal)
                {
                    sbCommandText.Append(value.ToString());
                }
                else if (value is DateTime)
                {
                    // SQL Server only supports ISO8601 with 3 digit precision on datetime,
                    // datetime2 (>= SQL Server 2008) parses the .net format, and will 
                    // implicitly cast down to datetime.
                    // Alternatively, use the format string "yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fffK"
                    // to match SQL server parsing
                    sbCommandText.Append("CAST('");
                    sbCommandText.Append(((DateTime)value).ToString(DATETIME_FORMAT_ROUNDTRIP));
                    sbCommandText.Append("' as datetime2)");
                }
                else if (value is DateTimeOffset)
                {
                    sbCommandText.Append('\'');
                    sbCommandText.Append(((DateTimeOffset)value).ToString(DATETIME_FORMAT_ROUNDTRIP));
                    sbCommandText.Append('\'');
                }
                else if (value is Guid)
                {
                    sbCommandText.Append('\'');
                    sbCommandText.Append(((Guid)value).ToString());
                    sbCommandText.Append('\'');
                }
                else if (value is byte[])
                {
                    var data = (byte[])value;
                    if (data.Length == 0)
                    {
                        sbCommandText.Append("NULL");
                    }
                    else
                    {
                        sbCommandText.Append("0x");
                        for (int i = 0; i < data.Length; i++)
                        {
                            sbCommandText.Append(data[i].ToString("x"));
                        }
                    }
                }
                else
                {
                    sbCommandText.Append("/* UNKNOWN DATATYPE: ");
                    sbCommandText.Append(value.GetType().ToString());
                    sbCommandText.Append(" *" + "/ N'");
                    sbCommandText.Append(value.ToString());
                    sbCommandText.Append('\'');
                }
            }
        }

        catch (Exception ex)
        {
            sbCommandText.AppendLine("/* Exception occurred while converting parameter: ");
            sbCommandText.AppendLine(ex.ToString());
            sbCommandText.AppendLine("*/");
        }
    }

    private static object unboxNullable(object value)
    {
        var typeOriginal = value.GetType();
        if (typeOriginal.IsGenericType
            && typeOriginal.GetGenericTypeDefinition() == typeof(Nullable<>))
        {
            // generic value, unboxing needed
            return typeOriginal.InvokeMember("GetValueOrDefault",
                System.Reflection.BindingFlags.Public |
                System.Reflection.BindingFlags.Instance |
                System.Reflection.BindingFlags.InvokeMethod,
                null, value, null);
        }
        else
        {
            return value;
        }
    }

    private static void logParameterType(SqlParameter param, StringBuilder sbCommandText)
    {
        switch (param.SqlDbType)
        {
            // variable length
            case SqlDbType.Char:
            case SqlDbType.NChar:
            case SqlDbType.Binary:
                {
                    sbCommandText.Append(param.SqlDbType.ToString().ToUpper());
                    sbCommandText.Append('(');
                    sbCommandText.Append(param.Size);
                    sbCommandText.Append(')');
                }
                break;
            case SqlDbType.VarBinary:
            case SqlDbType.Image:
                    {
                            sbCommandText.Append("VARBINARY");
                            sbCommandText.Append("(MAX /* Specified as ");
                            sbCommandText.Append(param.Size);
                            sbCommandText.Append(" */)");
                    }
                    break;
            case SqlDbType.VarChar:
            case SqlDbType.Text:
                    {
                            sbCommandText.Append("VARCHAR");
                            sbCommandText.Append("(MAX /* Specified as ");
                            sbCommandText.Append(param.Size);
                            sbCommandText.Append(" */)");
                    }
                    break;
            case SqlDbType.NVarChar:
            case SqlDbType.NText:
                    {
                            sbCommandText.Append("NVARCHAR");
                            sbCommandText.Append("(MAX /* Specified as ");
                            sbCommandText.Append(param.Size);
                            sbCommandText.Append(" */)");
                    }
                    break;
            // fixed length
            case SqlDbType.Bit:
            case SqlDbType.TinyInt:
            case SqlDbType.SmallInt:
            case SqlDbType.Int:
            case SqlDbType.BigInt:
            case SqlDbType.SmallMoney:
            case SqlDbType.Money:
            case SqlDbType.Decimal:
            case SqlDbType.Real:
            case SqlDbType.Float:
            case SqlDbType.Date:
            case SqlDbType.DateTime:
            case SqlDbType.DateTime2:
            case SqlDbType.DateTimeOffset:
            case SqlDbType.UniqueIdentifier:
                {
                    sbCommandText.Append(param.SqlDbType.ToString().ToUpper());
                }
                break;
            // Unknown
            case SqlDbType.Timestamp:
            default:
                {
                    sbCommandText.Append("/* UNKNOWN DATATYPE: ");
                    sbCommandText.Append(param.SqlDbType.ToString().ToUpper());
                    sbCommandText.Append(" *" + "/ ");
                    sbCommandText.Append(param.SqlDbType.ToString().ToUpper());
                }
                break;
        }
    }
}

1
谢谢你,这很全面! :-) - Alastair Maw
1
正是我所寻找的,谢谢。 - Xilmiki
1
这不需要在SQL字符串字面量前加上“N”前缀吗?否则你可能会得到很多“?”。默默地。糟糕。(至少对于SQL Server 2005而言-尚未检查较旧的版本。) - Paul Groke
@PaulGroke,干得好。我已经更新了,包括N前缀。 - Mitch
@Mitch:据我所知,SQL Server始终使用(并期望)小数点,而不是逗号。我错了吗?此外,正常值的往返应该可以工作。我认为ToString("G17", CultureInfo.InvariantCulture)对于floatdouble应该没问题,而ToString("G", CultureInfo.InvariantCulture)对于decimal也是如此。(MSDN说“R”格式在x64系统上并不总是往返double。这有点可爱,因为“R”实际上代表“round trip”。)但特殊值是个问题。但是再次提醒,SQL Server似乎无论如何都会出现问题。 - Paul Groke
显示剩余3条评论

7
我曾经遇到过这个问题,一些参数化查询或存储过程会导致 SqlException(大多数情况下是字符串或二进制数据被截断),而且这些语句很难调试(据我所知,目前 SQL Azure 并不支持 SQL Profiler)。
我在这里看到了很多相似的代码。最终,我将我的解决方案放入了一个 Sql-Library 项目中以供将来使用。
生成器可以在这里找到:https://github.com/jeroenpot/SqlHelper/blob/master/Source/Mirabeau.MsSql.Library/SqlGenerator.cs
它支持 CommandType.Text 和 CommandType.StoredProcedure。
如果您安装了 NuGet 包,则可以使用以下语句生成它:
SqlDebugHelper.CreateExecutableSqlStatement(sql, parameters);

还不错,它至少列出了每个参数的值,但仍然没有实际填充这些值。至少我可以使用记事本自己完成,谢谢! - Harvey Lin

5
如果您正在使用SQL Server,可以使用SQL Server Profiler(如果有的话)来查看实际执行的命令字符串。对于复制/粘贴测试目的,这可能很有用,但恐怕不能用于日志记录。

5
晚了一点,我知道,但我也想要这个功能,以便记录SQL。以下是简短的代码,满足我的需求。
以下代码会生成SQL语句,你可以在SSMS中复制/粘贴(它会将参数正确地替换为值)。你可以添加更多类型,但在这种情况下,它已经涵盖了我所使用的所有类型。
    private static void LogSQL(SqlCommand cmd)
        {
            string query = cmd.CommandText;

            foreach (SqlParameter prm in cmd.Parameters)
            {
                switch (prm.SqlDbType)
                {
                    case SqlDbType.Bit:
                        int boolToInt = (bool)prm.Value ? 1 : 0;
                        query = query.Replace(prm.ParameterName, string.Format("{0}", (bool)prm.Value ? 1 : 0));
                        break;
                    case SqlDbType.Int:
                        query = query.Replace(prm.ParameterName, string.Format("{0}", prm.Value));
                        break;
                    case SqlDbType.VarChar:
                        query = query.Replace(prm.ParameterName, string.Format("'{0}'", prm.Value));
                        break;
                    default:
                        query = query.Replace(prm.ParameterName, string.Format("'{0}'", prm.Value));
                        break;
                }
            }

            // the following is my how I write to my log - your use will vary
            logger.Debug("{0}", query);

            return;
        }

现在我可以在执行SQL之前记录它:
LogSQL(queryCmd)
queryCmd.ExecuteNonQuery()

2

我的解决方案:

public static class DbHelper
{
    public static string ToString(this DbParameterCollection parameters, string sqlQuery)
    {
        return parameters.Cast<DbParameter>().Aggregate(sqlQuery, (current, p) => current.Replace(p.ParameterName, p.Value.ToString()));
    }
}

2
使用了Flapper的代码的一部分来解决我的问题,该代码返回包括参数值在内的整个SQL字符串,可在MS SQL SMS中运行。
public string ParameterValueForSQL(SqlParameter sp)
    {
        string retval = "";

        switch (sp.SqlDbType)
        {
            case SqlDbType.Char:
            case SqlDbType.NChar:
            case SqlDbType.NText:
            case SqlDbType.NVarChar:
            case SqlDbType.Text:
            case SqlDbType.Time:
            case SqlDbType.VarChar:
            case SqlDbType.Xml:
            case SqlDbType.Date:
            case SqlDbType.DateTime:
            case SqlDbType.DateTime2:
            case SqlDbType.DateTimeOffset:
                if (sp.Value == DBNull.Value)
                {
                    retval = "NULL";
                }
                else
                {
                    retval = "'" + sp.Value.ToString().Replace("'", "''") + "'";
                }
                break;

            case SqlDbType.Bit:
                if (sp.Value == DBNull.Value)
                {
                    retval = "NULL";
                }
                else
                {
                    retval = ((bool)sp.Value == false) ? "0" : "1";
                }
                break;

            default:
                if (sp.Value == DBNull.Value)
                {
                    retval = "NULL";
                }
                else
                {
                    retval = sp.Value.ToString().Replace("'", "''");
                }
                break;
        }

        return retval;
    }


    public string CommandAsSql(SqlCommand sc)
    {
        string sql = sc.CommandText;

        sql = sql.Replace("\r\n", "").Replace("\r", "").Replace("\n", "");
        sql = System.Text.RegularExpressions.Regex.Replace(sql, @"\s+", " ");

        foreach (SqlParameter sp in sc.Parameters)
        {
            string spName = sp.ParameterName;
            string spValue = ParameterValueForSQL(sp);
            sql = sql.Replace(spName, spValue);
        }

        sql = sql.Replace("= NULL", "IS NULL");
        sql = sql.Replace("!= NULL", "IS NOT NULL");
        return sql;
    }

你的“解决方案”不起作用。你把 \r 和 \n 替换成了 "",但你应该使用 " "。此外,如果你有超过9个参数,它就不起作用了,因为替换 '@p1' 会将 '@p1' 和 '@p10' 都替换成各种疯狂的结果。复制参数列表并反转它是我正在做的快速修复。 - B H
此外,由于“is null”替换,您的代码无法用于更新命令。 - B H
确实,Flapper的代码没有处理DBNull,在基于它的CommandAsSQL库中存在问题:https://github.com/jphellemons/CommandAsSql/issues/1 - George Birbilis

2
我为自己编写了这个方法。我使用了Bruno Ratnieks的一部分代码。也许对某些人有用。
 public static string getQueryFromCommand(SqlCommand cmd)
    {
        StringBuilder CommandTxt = new StringBuilder();
        CommandTxt.Append("DECLARE ");
        List<string> paramlst = new List<string>();
        foreach (SqlParameter parms in cmd.Parameters)
        {
            paramlst.Add(parms.ParameterName);
            CommandTxt.Append(parms.ParameterName + " AS ");
            CommandTxt.Append(parms.SqlDbType.ToString());
            CommandTxt.Append(",");
        }

        if (CommandTxt.ToString().Substring(CommandTxt.Length-1, 1) == ",")
            CommandTxt.Remove(CommandTxt.Length-1, 1);
        CommandTxt.AppendLine();
        int rownr = 0;
        foreach (SqlParameter parms in cmd.Parameters)
        {
            string val = String.Empty;
            if (parms.DbType.Equals(DbType.String) || parms.DbType.Equals(DbType.DateTime))
                val = "'" + Convert.ToString(parms.Value).Replace(@"\", @"\\").Replace("'", @"\'") + "'";
            if (parms.DbType.Equals(DbType.Int16) || parms.DbType.Equals(DbType.Int32) || parms.DbType.Equals(DbType.Int64) || parms.DbType.Equals(DbType.Decimal) || parms.DbType.Equals(DbType.Double))
                val = Convert.ToString(parms.Value);

            CommandTxt.AppendLine();
            CommandTxt.Append("SET " + paramlst[rownr].ToString() + " = " + val.ToString());
            rownr += 1;
        }
        CommandTxt.AppendLine();
        CommandTxt.AppendLine();
        CommandTxt.Append(cmd.CommandText);
        return CommandTxt.ToString();
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接