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

我有以下代码:

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语句作为一个string,应该看起来像这样:

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

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

  • logging(失败)的语句
  • 有可能将其复制并粘贴到企业pipe理器进行testing

虽然不完美,但是我为TSQL敲了一些东西 – 可以很容易地调整其他口味…如果没有其他的东西,它会给你一个起点,为自己的改善:)

这对于在SSMS中使用“执行存储过程”类似的数据types和输出参数等做了一个确定的工作。 我们主要使用SP,所以“文本”命令不考虑参数等

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

为了logging目的,我恐怕没有更好的方法来做这个事情,而是自己来构buildstring:

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

对不起,我忘了.. p.Value.ToString()应该做的工作。

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

参数化的查询( CommandText那个)作为准备好的语句的等效语句被发送到SQL Server。 执行该命令时,参数和查询文本被分开处理。 在任何时候都不会生成完整的SQLstring。

您可以使用SQL事件探查器在幕后进行查看。

我需要一个类似的命令string变压器允许更详细的日志logging,所以我写了这一个。 它将产生在新的会话中重新执行命令所需的文本,包括输出参数和结构化参数。 这是轻微的考验,但要注意空头。

例:

 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(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 = true; 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("h2")); } } } 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.VarChar: case SqlDbType.NVarChar: case SqlDbType.VarBinary: { sbCommandText.Append(param.SqlDbType.ToString().ToUpper()); sbCommandText.Append("(MAX /* Specified as "); sbCommandText.Append(param.Size); sbCommandText.Append(" */)"); } break; // fixed length case SqlDbType.Text: case SqlDbType.NText: 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: case SqlDbType.Image: { 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; } } } 

如果您使用的是SQL Server,则可以使用SQL Server Profiler(如果有的话)来查看实际执行的命令string。 这将是有用的复制/粘贴testingpurpuses但不logging我害怕。

我也有这个问题,其中一些参数化查询或sp会给我一个SqlException(主要是string或二进制数据将被截断),以及难以debugging的语句(据我所知,目前没有sql-profiler支持SQL Azure)

我在这里看到很多类似的代码。 我最终将我的解决scheme放在一个Sql-Library项目中,以备将来使用。

生成器可在这里: https : //github.com/jeroenpot/SqlHelper/blob/master/Source/Mirabeau.MsSql.Library/SqlGenerator.cs

它支持CommandType.Text和CommandType.StoredProcedure

如果你安装nuget-package,你可以用下面的语句生成它:

 SqlDebugHelper.CreateExecutableSqlStatement(sql, parameters); 

我的解决scheme使用Flapper的代码部分,它返回包含参数值的整个SQLstring以在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; } 

事件探查器是你最好的select。

由于涉及到准备+执行步骤,您可能需要从configuration文件复制一组语句。

如果只是在结果查询中检查参数是如何格式化的,那么大多数DBMS将允许从空闲查询文字。 从而:

 Using cmd As SqlCommand = Connection.CreateCommand cmd.CommandText = "SELECT @Value" cmd.Parameters.AddWithValue("@Value", "myValue") Return cmd.ExecuteScalar End Using 

这样你可以看到报价是否加倍等

这是我用来输出存储过程的参数列表到debugging控制台:

 string query = (from SqlParameter p in sqlCmd.Parameters where p != null where p.Value != null select string.Format("Param: {0} = {1}, ", p.ParameterName, p.Value.ToString())).Aggregate(sqlCmd.CommandText, (current, parameter) => current + parameter); Debug.WriteLine(query); 

这将产生一个类似于这样的控制台输出:

 Customer.prGetCustomerDetails: @Offset = 1, Param: @Fetch = 10, Param: @CategoryLevel1ID = 3, Param: @VehicleLineID = 9, Param: @SalesCode1 = bce, 

我把这个代码直接放在我希望debugging的任何过程之下,类似于一个sql profiler会话,但是在C#中。

Kon的答案的修改版本,因为它只部分与类似的命名参数。 使用stringreplacefunction的缺点。 除此之外,我在解决scheme上给了他充分的信任。

  private string GetActualQuery(SqlCommand sqlcmd) { string query = sqlcmd.CommandText; string parameters = ""; string[] strArray = System.Text.RegularExpressions.Regex.Split(query, " VALUES "); //Reconstructs the second half of the SQL Command parameters = "("; int count = 0; foreach (SqlParameter p in sqlcmd.Parameters) { if (count == (sqlcmd.Parameters.Count - 1)) { parameters += p.Value.ToString(); } else { parameters += p.Value.ToString() + ", "; } count++; } parameters += ")"; //Returns the string recombined. return strArray[0] + " VALUES " + parameters; } 

我的解决scheme

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

这个解决scheme现在适合我。 也许对某人有用。 请原谅所有的冗余。

  Public Shared Function SqlString(ByVal cmd As SqlCommand) As String Dim sbRetVal As New System.Text.StringBuilder() For Each item As SqlParameter In cmd.Parameters Select Case item.DbType Case DbType.String sbRetVal.AppendFormat("DECLARE {0} AS VARCHAR(255)", item.ParameterName) sbRetVal.AppendLine() sbRetVal.AppendFormat("SET {0} = '{1}'", item.ParameterName, item.Value) sbRetVal.AppendLine() Case DbType.DateTime sbRetVal.AppendFormat("DECLARE {0} AS DATETIME", item.ParameterName) sbRetVal.AppendLine() sbRetVal.AppendFormat("SET {0} = '{1}'", item.ParameterName, item.Value) sbRetVal.AppendLine() Case DbType.Guid sbRetVal.AppendFormat("DECLARE {0} AS UNIQUEIDENTIFIER", item.ParameterName) sbRetVal.AppendLine() sbRetVal.AppendFormat("SET {0} = '{1}'", item.ParameterName, item.Value) sbRetVal.AppendLine() Case DbType.Int32 sbRetVal.AppendFormat("DECLARE {0} AS int", item.ParameterName) sbRetVal.AppendLine() sbRetVal.AppendFormat("SET {0} = {1}", item.ParameterName, item.Value) sbRetVal.AppendLine() Case Else Stop End Select Next sbRetVal.AppendLine("") sbRetVal.AppendLine(cmd.CommandText) Return sbRetVal.ToString() End Function 

我有同样的确切的问题,并在阅读这些答案错误地决定不可能得到确切的结果查询。 我错了。

解决scheme:SQL Server Management Studio打开Activity Monitor ,将进程部分缩小到应用程序在连接string中使用的login用户名,数据库或应用程序名称。 当调用数据库刷新Activity Monitor 。 当你看到这个过程时,右键单击它并View Details

请注意,这可能不是一个繁忙的数据库可行的选项。 但是,您应该能够使用这些步骤大幅缩小结果。

作为@pkExec和@Alok提到,使用replace不能在100%的情况下工作。 这是我在DAL中使用的解决scheme,它使用RegExp仅“匹配整个单词”并正确地格式化数据types。 因此,生成的SQL可以直接在MySQL Workbench(或SQLSMS等)中testing:)

(根据使用的DBMSreplaceMySQLHelper.EscapeString()函数。)

 Dim query As String = cmd.CommandText query = query.Replace("SET", "SET" & vbNewLine) query = query.Replace("WHERE", vbNewLine & "WHERE") query = query.Replace("GROUP BY", vbNewLine & "GROUP BY") query = query.Replace("ORDER BY", vbNewLine & "ORDER BY") query = query.Replace("INNER JOIN", vbNewLine & "INNER JOIN") query = query.Replace("LEFT JOIN", vbNewLine & "LEFT JOIN") query = query.Replace("RIGHT JOIN", vbNewLine & "RIGHT JOIN") If query.Contains("UNION ALL") Then query = query.Replace("UNION ALL", vbNewLine & "UNION ALL" & vbNewLine) ElseIf query.Contains("UNION DISTINCT") Then query = query.Replace("UNION DISTINCT", vbNewLine & "UNION DISTINCT" & vbNewLine) Else query = query.Replace("UNION", vbNewLine & "UNION" & vbNewLine) End If For Each par In cmd.Parameters If par.Value Is Nothing OrElse IsDBNull(par.Value) Then query = RegularExpressions.Regex.Replace(query, par.ParameterName & "\b", "NULL") ElseIf TypeOf par.Value Is Date Then query = RegularExpressions.Regex.Replace(query, par.ParameterName & "\b", "'" & Format(par.Value, "yyyy-MM-dd HH:mm:ss") & "'") ElseIf TypeOf par.Value Is TimeSpan Then query = RegularExpressions.Regex.Replace(query, par.ParameterName & "\b", "'" & par.Value.ToString & "'") ElseIf TypeOf par.Value Is Double Or TypeOf par.Value Is Decimal Or TypeOf par.Value Is Single Then query = RegularExpressions.Regex.Replace(query, par.ParameterName & "\b", Replace(par.Value.ToString, ",", ".")) ElseIf TypeOf par.Value Is Integer Or TypeOf par.Value Is UInteger Or TypeOf par.Value Is Long Or TypeOf par.Value Is ULong Then query = RegularExpressions.Regex.Replace(query, par.ParameterName & "\b", par.Value.ToString) Else query = RegularExpressions.Regex.Replace(query, par.ParameterName & "\b", "'" & MySqlHelper.EscapeString(CStr(par.Value)) & "'") End If Next 

例:

 SELECT * FROM order WHERE order_status = @order_status AND order_date = @order_date 

将会生成:

 SELECT * FROM order WHERE order_status = 'C' AND order_date = '2015-01-01 00:00:00' 

sql命令的查询将使用exec sp_executesql来执行,所以这里有另外一种方法来将语句作为一个string(SqlCommand扩展方法):

 public static string ToSqlStatement(this SqlCommand cmd) { return $@"EXECUTE sp_executesql N'{cmd.CommandText.Replace("'", "''")}'{cmd.Parameters.ToSqlParameters()}"; } private static string ToSqlParameters(this SqlParameterCollection col) { if (col.Count == 0) return string.Empty; var parameters = new List<string>(); var parameterValues = new List<string>(); foreach (SqlParameter param in col) { parameters.Add($"{param.ParameterName}{param.ToSqlParameterType()}"); parameterValues.Add($"{param.ParameterName} = {param.ToSqlParameterValue()}"); } return $",N\'{string.Join(",", parameters)}\',{string.Join(",", parameterValues)}"; } private static object ToSqlParameterType(this SqlParameter param) { var paramDbType = param.SqlDbType.ToString().ToLower(); if (param.Precision != 0 && param.Scale != 0) return $"{paramDbType}({param.Precision},{param.Scale})"; if (param.Precision != 0) return $"{paramDbType}({param.Precision})"; switch (param.SqlDbType) { case SqlDbType.VarChar: case SqlDbType.NVarChar: string s = param.SqlValue?.ToString() ?? string.Empty; return paramDbType + (s.Length > 0 ? $"({s.Length})" : string.Empty); default: return paramDbType; } } private static string ToSqlParameterValue(this SqlParameter param) { switch (param.SqlDbType) { case SqlDbType.Char: case SqlDbType.Date: case SqlDbType.DateTime: case SqlDbType.DateTime2: case SqlDbType.DateTimeOffset: case SqlDbType.NChar: case SqlDbType.NText: case SqlDbType.NVarChar: case SqlDbType.Text: case SqlDbType.Time: case SqlDbType.VarChar: case SqlDbType.Xml: return $"\'{param.SqlValue.ToString().Replace("'", "''")}\'"; case SqlDbType.Bit: return param.SqlValue.ToBooleanOrDefault() ? "1" : "0"; default: return param.SqlValue.ToString().Replace("'", "''"); } } public static bool ToBooleanOrDefault(this object o, bool defaultValue = false) { if (o == null) return defaultValue; string value = o.ToString().ToLower(); switch (value) { case "yes": case "true": case "ok": case "y": return true; case "no": case "false": case "n": return false; default: bool b; if (bool.TryParse(o.ToString(), out b)) return b; break; } return defaultValue; } 

一个class轮:

 string.Join(",", from SqlParameter p in cmd.Parameters select p.ToString()) 

我为我写了这个方法。 我使用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(); }