2010-05-06 3 views
7

J'ai un problème avec le morceau de code suivant. Je passe un paramètre (List<SqlParameter>) à une méthode exécutant le code suivant. Lorsqu'il exécute SQL Server, il génère une erreur indiquant que le proc attend un paramètre qui n'a pas été fourni. Je connais cette erreur et je la comprends, et en parcourant le code, je peux voir que l'objet cmdExecuteReader a une collection de paramètres avec le nom et la valeur corrects. Quel pourrait être le problème?Problème SqlCommand.Parameters.AddWithValue: Procédure ou fonction X attend le paramètre @Y, qui n'a pas été fourni

 public SqlDataReader ExecuteReader(string storedProcedure, List<SqlParameter> parameters = null) 
     { 
        SqlCommand cmdExecuteReader = new SqlCommand() 
        { 
         CommandType = System.Data.CommandType.Text, 
         Connection = conn, 
         CommandText = storedProcedure 
        }; 

        if (parameters != null) 
        { 
         foreach (SqlParameter param in parameters) 
         { 
          cmdExecuteReader.Parameters.AddWithValue(param.ParameterName, param.Value); 
         } 
        } 

        if (conn.State == System.Data.ConnectionState.Closed) 
         conn.Open(); 
        return cmdExecuteReader.ExecuteReader(); 
     } 

Répondre

10

Le .Value ensemble à null pour l'un des paramètres? Si oui, ils ne sont pas envoyés. Essayez:

cmdExecuteReader.Parameters.AddWithValue(param.ParameterName, 
     param.Value ?? DBNull.Value); 

(notez le null-coalescent avec DBNull.Value)

En outre, notez que AddWithValue peut influer sur votre réutilisation recherche plan, comme (pour les chaînes, etc.), il utilise la longueur de la valeur. Si vous avez besoin de performances maximales, il est préférable de configurer le paramètre manuellement avec les tailles définies.

Notez également que potentiellement certains des paramètres dans la liste entrante pourraient être entrée-sortie, sortie ou résultat. Je serais très tenté de se substituer à quelque chose comme:

SqlParameter newParam = cmdExecuteReader.Parameters.Add(
     param.ParameterName, param.SqlDbType, param.Size); 
newParam.Value = param.Value ?? DBNull.Value; 
newParam.Direction = param.Direction; 
+0

+1. Personnellement, je n'utilise pas AddWithValue, préférant définir explicitement les types de données (et les tailles) - sinon vous risquez de vous retrouver avec des suppositions incorrectes (comme les valeurs de chaînes .NET passées en tant que NVARCHAR) dont je suis paranoïaque – AdaTheDev

0

Je l'ai fait les choses que vous essayez de faire, voici quelques exemples:

public int ChangeState(int id, int stateId) 
{ 
    return DbUtil.ExecuteNonQuerySp("changeDossierState", Cs, new { id, stateId }); 
} 

public IEnumerable<Dossier> GetBy(int measuresetId, int measureId, DateTime month) 
{ 
    return DbUtil.ExecuteReaderSp<Dossier>("getDossiers", Cs, new { measuresetId, measureId, month }); 
} 

Je vous recommande de regarder here

et de télécharger la solution d'échantillons (où un projet d'échantillon DAL est inclus) http://valueinjecter.codeplex.com/

Questions connexes