2010-05-07 11 views
14

Lo que intento hacer es crear algún comando sql arbitrario con parámetros, establecer los valores y tipos de los parámetros, y luego devolver el comando sql analizado, con los parámetros incluidos. No ejecutaré directamente este comando en una base de datos sql, por lo que no será necesaria ninguna conexión. Así que si me encontré a continuación el programa de ejemplo, yo esperaría a ver el texto siguiente (o algo similar):¿Es posible obtener el texto analizado de un SqlCommand con SqlParameters?

WITH SomeTable (SomeColumn) 
AS 
(
    SELECT N':)' 
    UNION ALL 
    SELECT N'>:o' 
    UNION ALL 
    SELECT N'^_^' 
) 
SELECT SomeColumn FROM SomeTable 

Y el programa de ejemplo es:

using System; 
using System.Data; 
using System.Data.SqlClient; 

namespace DryEraseConsole 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      const string COMMAND_TEXT = @" 
WITH SomeTable (SomeColumn) 
AS 
(
    SELECT N':)' 
    UNION ALL 
    SELECT N'>:o' 
    UNION ALL 
    SELECT @Value 
) 
SELECT SomeColumn FROM SomeTable 
"; 
      SqlCommand cmd = new SqlCommand(COMMAND_TEXT); 
      cmd.CommandText = COMMAND_TEXT; 
      cmd.Parameters.Add(new SqlParameter 
      { 
       ParameterName = "@Value", 
       Size = 128, 
       SqlDbType = SqlDbType.NVarChar, 
       Value = "^_^" 
      }); 
      Console.WriteLine(cmd.CommandText); 
      Console.ReadKey(); 
     } 
    } 
} 

Es esto algo que se puede lograr usando las bibliotecas .net estándar? La búsqueda inicial dice que no, pero espero estar equivocado.

Respuesta

20

Tiene una idea errónea de cómo funcionan las consultas parametrizadas. El "texto analizado" del que habla es nunca creado, y los valores de los parámetros son nunca sustituidos directamente en la cadena de consulta.

Es por eso que es tan importante utilizar consultas parametrizadas — que tiene completa segregación de datos de consulta de código de consulta. Los datos son datos, el código es código y nunca los dos se encontrarán. Por lo tanto, no hay posibilidad de inyección de sql.

Lo que significa es que si usted tiene un CommandText así:

SELECT SomeColumn FROM SomeTable WHERE ID= @ID 

en lugar de en última instancia, ejecutar una consulta que tiene este aspecto:

SELECT SomeColumn FROM SomeTable WHERE ID= 123 

que realmente ejecute algo más parecido a esto:

DECLARE @ID Int 
Set @ID = RetrieveQueryDataItem("@ID") 
SELECT SomeColumn FROM SomeTable WHERE ID= @ID 

Ahora, esto no es exactamente lo que sucede; el motor no transforma el código así. En su lugar, utiliza el procedimiento sp_executesql. Pero esto debería ayudarte a entender lo que está pasando.

+2

Gracias, esto es exactamente lo que necesitaba escuchar. Saber que sp_executesql es lo que se llama detrás de escena explica todo. – Burg

1

Me sentiría tentado de estudiar el uso de LINQ, ya que le dará el control que desea en su código C#.

+1

Desafortunadamente, Linq-To-Sql es un ORM en su mayor parte, y eso no es lo que estoy haciendo. Lo que necesito hacer es una generación avanzada de T-SQL (inserciones masivas, por ejemplo). – Burg

3

Joel Coehoorn es correcto, no es sólo una sustitución de cadenas o de carácter de escape adición simple, etc.

Puede, sin embargo, ver sus parámetros para ver si sus valores son tal y como quieres:

foreach (IDataParameter i in cmd.Parameters) 
{ 
    Console.WriteLine(i.Value.ToString()); 
} 
2

El objeto SQLCommand no intercambia los parámetros del valor en el texto del comando y ejecuta eso. Llama al sp_execute sql con el texto exacto que suministra y luego proporciona la lista de parámetros. Use el generador de perfiles SQL contra una base de datos y verá lo que quiero decir.

¿Qué es lo que realmente está tratando de lograr aquí?

+0

Estaba tratando de encontrar una manera fácil de generar algún texto de comando sql (estos comandos se ejecutarían en sentido ascendente, no en el lugar). La funcionalidad de las consultas sería demasiado compleja para que la maneje Linq-To-Sql (no creo que LINQ haga inserciones masivas, T-SQL y similares). También esperaba poder evitar hacer el enfoque StringBuilder también. – Burg

Cuestiones relacionadas