Ajout de paramètres à IDbCommand

je crée une petite fonction helper pour retourner un DataTable. Je voudrais travailler à travers tous les fournisseurs ADO.Net prise en charge, j'ai donc pensé à faire de tout utiliser IDbCommand ou DbCommand dans la mesure du possible.

j'ai atteint un point d'achoppement avec le code suivant:

    private static DataTable QueryImpl(ref IDbConnection conn, String SqlToExecute, CommandType CommandType, Array Parameters)
    {
        SetupConnection(ref conn);
        // set the capacity to 20 so the first 20 allocations are quicker...
        DataTable dt = new DataTable();
        using (IDbCommand cmd = conn.CreateCommand())
        {
            cmd.CommandText = SqlToExecute;
            cmd.CommandType = CommandType;
            if (Parameters != null && Parameters.Length > 0)
            {
                for (Int32 i = 0; i < Parameters.Length; i++)
                {
                    cmd.Parameters.Add(Parameters.GetValue(i));
                }
            }
            dt.Load(cmd.ExecuteReader(), LoadOption.OverwriteChanges);
        }
        return dt;
    }

quand ce code est exécuté, je reçois un InvalidCastException qui stipule ce qui suit:

la section SqlParameterCollection accepte uniquement les objets de type SqlParameter Non-null, pas des objets String.

Le code est plus sur la ligne:

cmd.Parameters.Add(Parameters.GetValue(i));

des idées?

toute amélioration au code ci-dessus est appréciée.


solution actuelle:

    private static readonly Regex regParameters = new Regex(@"@w+", RegexOptions.Compiled);
    private static DataTable QueryImpl(ref DbConnection conn, String SqlToExecute, CommandType CommandType, Object[] Parameters)
    {
        SetupConnection(ref conn);
        DataTable dt = new DataTable();
        using (DbCommand cmd = conn.CreateCommand())
        {
            cmd.CommandText = SqlToExecute;
            cmd.CommandType = CommandType;
            if (Parameters != null && Parameters.Length > 0)
            {
                MatchCollection cmdParams = regParameters.Matches(cmd.CommandText);
                List<String> param = new List<String>();
                foreach (var el in cmdParams)
                {
                    if (!param.Contains(el.ToString()))
                    {
                        param.Add(el.ToString());
                    }
                }
                Int32 i = 0;
                IDbDataParameter dp;
                foreach (String el in param)
                {
                    dp = cmd.CreateParameter();
                    dp.ParameterName = el;
                    dp.Value = Parameters[i++];
                    cmd.Parameters.Add(dp);
                }
            }
            dt.Load(cmd.ExecuteReader(), LoadOption.OverwriteChanges);
        }
        return dt;
    } 

Merci pour les idées / liens etc. :)

37
demandé sur Stuart Blackler 2011-11-23 02:44:25

6 réponses

je crois que IDbCommand a une méthode CreateParameter ():

var parameter = command.CreateParameter();
parameter.ParameterName = "@SomeName";
parameter.Value = 1;

command.Parameters.Add(parameter);
72
répondu Dismissile 2011-11-23 14:25:13

Vous pouvez ajouter le code de la réponse acceptée à une méthode d'extension:

public static class DbCommandExtensionMethods
{
    public static void AddParameter (this IDbCommand command, string name, object value)
    {
        var parameter = command.CreateParameter();
        parameter.ParameterName = name;
        parameter.Value = value;
        command.Parameters.Add(parameter);
    }
}
18
répondu onestarblack 2016-01-28 15:10:04

je sais que c'est pas ce que vous demandez, mais j'ai beaucoup plus simple et plus robuste solution à offrir.

la bibliothèque de Microsoft Patterns and Practices inclut un bloc D'Application D'accès aux données qui est incroyablement puissant et facile à utiliser. Un exemple pour exécuter une procédure stockée et retourner un ensemble de données est montré ci-dessous à partir de notre code actuel:

 object[] ParameterValues = new object[] {"1",DateTime.Now, 12, "Completed", txtNotes.Text};
 Database db = DatabaseFactory.CreateDatabase("ConnectionStringName");
 DataSet ds =  = db.ExecuteDataSet("StoredProcName", ParameterValues);

peu importe que la connexion soit OleDb, ODBC, etc. Le nom de connexion dans la première ligne de code est juste le nom de la Consternating tel que défini dans la .fichier de configuration. Vous passez dans une Chaîne de Connexion nom de, procédure stockée nom, et un tableau d'objets, qui constituent les paramètres. Ce n'est qu'une des nombreuses fonctions sweet disponibles.

Vous obtiendrez tout ce que vous essayez de construire et puis un peu.

Le site officiel est ici: http://msdn.microsoft.com/en-us/library/ff648951.aspx

pour vous sauver de la recherche, les classes de données la documentation est disponible ici: http://msdn.microsoft.com/en-us/library/microsoft.practices.enterpriselibrary.data(PandP.50).aspx

(et c'est gratuit à partir de Microsoft, et mis à jour régulièrement.)

2
répondu David 2011-11-22 23:02:27

Parameters paramètre doit être de type IDataParameter[] et, compte tenu du texte d'erreur, la mise en œuvre concrète doit être un SqlParameter[] type.

si vous souhaitez conserver votre signature, vous aurez besoin d'une usine pour dériver la mise en œuvre concrète nécessaire.

0
répondu Austin Salonen 2011-11-22 22:59:29

cette réponse est destinée à un but un peu plus spécifique que ce que vous faites, mais en s'appuyant sur @Dismissile's réponse, j'ai utilisé un Dictionary pour fournir le nom et la valeur du paramètre à un foreach boucle dans mon projet personnel.

using( IDbCommand dbCommand = dbConnection.CreateCommand() )
{
    dbCommand.CommandText = Properties.Settings.Default.UpdateCommand;
    Dictionary<string,object> values = new Dictionary<string,object>()
    {
        {"@param1",this.Property1},
        {"@param2",this.Property2},
        // ...
    };
    foreach( var item in values )
    {
        var p = dbCommand.CreateParameter();
        p.ParameterName = item.Key;
        p.Value = item.Value;
        dbCommand.Parameters.Add(p);
    }
}
0
répondu Drew Chapin 2017-07-24 18:33:49

Ajouter using System.Data.SqlClient; et cmd.Parameters.Add(new SqlParameter("@parameterName", value));

-2
répondu Sidron 2016-02-24 12:53:02