从 SqlCommand 对象发送啥 SQL

Posted

技术标签:

【中文标题】从 SqlCommand 对象发送啥 SQL【英文标题】:What SQL is being sent from a SqlCommand object从 SqlCommand 对象发送什么 SQL 【发布时间】:2011-02-06 08:59:42 【问题描述】:

我在基于 c# 的 asp.net 页面上有一个 SqlCommand 对象。 SQL 和传递的参数大部分时间都在工作。我有一个案例不工作,我收到以下错误:

字符串或二进制数据将被截断。声明已终止。

我了解错误,但数据库中的所有列都应该足够长以容纳发送的所有内容。

我的问题,

有没有办法查看从 SqlCommand 对象发送到数据库的实际 SQL 是什么?我希望能够在发生错误时通过电子邮件发送 SQL。

谢谢, 贾斯汀

【问题讨论】:

【参考方案1】:

虽然您无法将其插入企业管理器之类的东西来运行它,但它适用于日志记录。

public static string ToReadableString(this IDbCommand command)

    StringBuilder builder = new StringBuilder();
    if (command.CommandType == CommandType.StoredProcedure)
        builder.AppendLine("Stored procedure: " + command.CommandText);
    else
        builder.AppendLine("Sql command: " + command.CommandText);
    if (command.Parameters.Count > 0)
        builder.AppendLine("With the following parameters.");
    foreach (IDataParameter param in command.Parameters)
    
        builder.AppendFormat(
            "     Paramater 0: 1",
            param.ParameterName,
            (param.Value == null ? 
            "NULL" : param.Value.ToString())).AppendLine();
    
    return builder.ToString();

【讨论】:

你拯救了我的一天!不允许使用分析器,这是获取实际 SQL,然后从 SSMS 或企业管理器运行它的好方法。【参考方案2】:

您需要使用 SQL Server Profiler 来观察来自应用程序的内容。我相信它可以向您展示您需要查看的 SQL 和参数。

【讨论】:

这个工具应该是你最好的朋友。 这是最好的,微软使用一些愚蠢的存储过程而不是生成实际的 SQL 语句。这让开发人员(我)变得疯狂。为什么他们必须如此倒退! 你指的是哪个存储过程?【参考方案3】:

虽然不完美,但这是我为 TSQL 设计的一些东西 - 可以很容易地调整为其他风格......如果没有别的,它会给你一个起点,让你自己改进 :)

这在数据类型和输出参数等方面做得很好,类似于在 SSMS 中使用“执行存储过程”。我们主要使用 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);

【讨论】:

请注意,这需要StringExtensions.cs 和ObjectExtensions.cs,但让SQL 更适合SQL Server。 我没有发现我在代码中留下了我自己的扩展方法(它们不是你提到的,但做同样的事情)但希望方法名称暗示它们的上下文!跨度> 【参考方案4】:

查看这个问题,它应该提供您正在寻找的内容。

Get the generated SQL statement from a SqlCommand object?

【讨论】:

以上是关于从 SqlCommand 对象发送啥 SQL的主要内容,如果未能解决你的问题,请参考以下文章

SqlCommand.ExecuteReader() 啥时候返回 null?

SqlCommand.CommandTimeout 和 SqlConnection.ConnectionTimeout 有啥区别?

MYSQL 系统命令 源码定位

将 gridview 行数据添加到文本框和标签中

从 .net 中的 Generic T 获取 SqlCommand 类型

使用 SqlCommand 从多个表中删除