2009-08-10 9 views
5

Creé un SqlCommand con una consulta SQL que contiene parámetros. I luego de agregar todos los parámetros a la clase.¿Hay alguna forma de recuperar el texto completo de sql desde SqlCommand después de la sustitución de param?

¿Hay alguna manera fácil de ver la consulta SQL resultante antes de que se envíe a la base de datos?

Esto sería útil para la depuración. (Por ejemplo, la copia de toda la consulta y ejecutarlo en el estudio de gestión para tratar de identificar problemas)

R

Respuesta

4

No, porque hay sustitución sucede en realidad. La consulta se pasa al servidor como está, y los parámetros se pasan por separado.

Sin embargo, puede escribir un método para reemplazar marcadores de posición de parámetros con los valores de parámetros reales ... eso es lo que hice en una de mis aplicaciones, publicaré el código tan pronto como pueda.


Este es el código que utilizo, pero es para una base de datos Oracle Lite, por lo que requerirá algunas adaptaciones para usarlo con otro RDBMS.

public void Log(IDbCommand cmd) 
    { 
     StringBuilder sb = new StringBuilder(cmd.CommandText); 
     for (int i = 0; i < cmd.Parameters.Count; i++) 
     { 
      int pos = sb.ToString().IndexOf("?"); 
      if (pos > 0) 
       sb.Replace("?", FormatParameter(cmd.Parameters[i]), pos, 1); 
     } 
     Log(sb.ToString()); 
    } 

    private string FormatParameter(object prm) 
    { 
     IDbDataParameter p = prm as IDbDataParameter; 
     if (p.Value == null || p.Value == DBNull.Value) 
      return "NULL"; 
     switch (p.DbType) 
     { 
      case DbType.AnsiString: 
      case DbType.AnsiStringFixedLength: 
      case DbType.String: 
      case DbType.StringFixedLength: 
       string s = p.Value as string; 
       return string.Format("'{0}'", s.Replace("'", "''")); 

      case DbType.Binary: 
       byte[] b = p.Value as byte[]; 
       return HexString(b); 

      case DbType.Date: 
      case DbType.DateTime: 
      case DbType.DateTime2: 
       DateTime d = (DateTime)p.Value; 
       return string.Format("to_date('{0}', 'dd/mm/yyyy hh24:mi')", d.ToString("dd/MM/yyyy HH:mm")); 

      default: 
       return p.Value.ToString(); 
     } 
    } 

    private string HexString(byte[] bytes) 
    { 
     StringBuilder sb = new StringBuilder(); 
     for (int i=0; i < bytes.Length; i++) 
      sb.AppendFormat("{0:X2}", bytes[i]); 
     return sb.ToString(); 
    } 
+0

genial ... ¡esto ayuda mucho! – Toad

2

Bueno, se puede ver toda la consulta en SQL (la verdad es que es después que ha sido enviado a la base de datos), pero te da una manera fácil de copiar y pegar la declaración por lo que se puede depurar con eso dentro de Management Studio.

Simplemente agregue un nuevo rastreo, ejecute el código que hace la llamada a la base de datos, luego copie y pegue el comando de los eventos de captura resultantes.

+0

El Analizador de SQL es tu amigo. – pjp

+0

¿funciona esto incluso cuando mi acceso a la base de datos está limitado a solo una cadena de conexión? ¿O necesito más acceso para ejecutar un generador de perfiles que pueda rastrear? – Toad

+0

¿Las credenciales que está utilizando tienen los derechos de administrador del sistema? Si no, entonces podrías ser SOL. Posiblemente entonces, el Código de Thomas es su mejor apuesta. – davewasthere

0

Acabo de volver a leer su pregunta antes de publicar esto. Si bien esta técnica probablemente no se puede aplicar directamente a .net, es posible que pueda resolver algo similar. Entonces:

Recientemente tuve que hacer una gran cantidad de codificación dinámica en T-SQL, y he creado la siguiente rutina. Suponemos que tienes un trozo de código de este modo:

DECLARE 
    @Command nvarchar(max) 
,@SearchFor int 

SET @Command = 'SELECT * from MyTable where PrimaryKey = @SearchFor' 
SET @SearchFor = 1 

EXECUTE sp_executesql 
    @Command 
,N'@SearchFor int' 
,@SearchFor 

Esto es por supuesto muy simplisitc - si usted tiene que hacer código dinámico, que va a tener consultas complejas a tremendamente compleja, y como se He descubierto que esto puede ser muy difícil de depurar. Así es como me gustaría volver a escribir el código anterior:

DECLARE 
    @Command nvarchar(max) 
,@SearchFor int 
,@Debug  int 
    -- 0 = Run it 
    -- 1 = Run and display it 
    -- 2 = Display it 

SET @Command = 'SELECT * from MyTable where PrimaryKey = @SearchFor' 
SET @SearchFor = 1 
SET @Debug = 1 

IF @Debug > 0 
    -- Show the command that would be run 
    PRINT replace(@Command, '@SearchFor', cast(@SearchFor as varchar(10))) 

IF @Debug < 2 
    -- Run it 
    EXECUTE sp_executesql 
     @Command 
    ,N'@SearchFor int' 
    ,@SearchFor 

Esto es código extra para escribir y depurar, pero una vez que esté en su lugar de trabajo y que puede ser muy valiosa en situaciones de depuración. Si es parte de un procedimiento almacenado, haga de @Debug un parámetro predeterminado en 0 y asegúrese de que si se establece en 2, el procedimiento en realidad no hace nada.

+0

Puedo apreciar que el pequeño esfuerzo extra, claramente da muchos beneficios en el departamento de depuración. Debería crear algo similar (si ya no existe nada así). – Toad

Cuestiones relacionadas