Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

À partir de .NET, puis-je obtenir la chaîne SQL complète générée par un objet SqlCommand (avec des paramètres SQL) ?

Une simple boucle remplaçant tous les noms de paramètres par leurs valeurs vous fournira quelque chose de similaire au résultat final, mais il y a plusieurs problèmes.

  1. Étant donné que le SQL n'est jamais réellement reconstruit à l'aide des valeurs de paramètre, des éléments tels que les retours à la ligne et les guillemets n'ont pas besoin d'être pris en compte
  2. Les noms de paramètres dans les commentaires ne sont jamais réellement traités pour leur valeur, mais laissés tels quels

Avec ceux en place, et en tenant compte des noms de paramètres qui commencent par les mêmes caractères, comme @NAME et @NAME_FULL , nous pouvons remplacer tous les noms de paramètres par la valeur qui serait à la place de ce paramètre :

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

il reste cependant un problème avec cela, et c'est que si un paramètre est une chaîne, alors le SQL qui ressemble initialement à ceci :

SELECT * FROM yourtable WHERE table_code = @CODE

ressemblera à ceci :

SELECT * FROM yourtable WHERE table_code = SOME CODE WITH SPACES

Ce n'est clairement pas du SQL légal, nous devons donc également tenir compte de certains types de paramètres :

DbType[] quotedParameterTypes = new DbType[] {
    DbType.AnsiString, DbType.Date,
    DbType.DateTime, DbType.Guid, DbType.String,
    DbType.AnsiStringFixedLength, DbType.StringFixedLength
};
string query = cmd.CommandText;

var arrParams = new SqlParameter[cmd.Parameters.Count];
cmd.Parameters.CopyTo(arrParams, 0);

foreach (SqlParameter p in arrParams.OrderByDescending(p => p.ParameterName.Length))
{
    string value = p.Value.ToString();
    if (quotedParameterTypes.Contains(p.DbType))
        value = "'" + value + "'";
    query = query.Replace(p.ParameterName, value);
}