将参数添加到IDbCommand
我正在创build一个小帮助函数来返回一个DataTable
。 我想在ADO.Net
支持的所有提供者中工作,所以我想尽可能使所有的东西都使用IDbCommand
或DbCommand
。
我用下面的代码达到了一个绊脚石:
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; }
执行此代码时,我收到一个InvalidCastException
,其中声明以下内容:
SqlParameterCollection只接受非空的SqlParametertypes对象,而不是String对象。
代码落在行上:
cmd.Parameters.Add(Parameters.GetValue(i));
有任何想法吗?
上述代码的任何改进表示赞赏。
实际解决scheme
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; }
感谢您的想法/链接等:)
我相信IDbCommand有一个CreateParameter()方法:
var parameter = command.CreateParameter(); parameter.ParameterName = "@SomeName"; parameter.Value = 1; command.Parameters.Add(parameter);
您可以将接受的答案的代码添加到扩展方法:
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); } }
我知道这不是你要问的,但我有一个更简单,更强大的解决scheme提供。
Microsoft模式和实践库包含一个非常强大且易于使用的数据访问应用程序块。 下面从我们的实际代码中显示了执行存储过程和返回数据集的示例:
object[] ParameterValues = new object[] {"1",DateTime.Now, 12, "Completed", txtNotes.Text}; Database db = DatabaseFactory.CreateDatabase("ConnectionStringName"); DataSet ds = = db.ExecuteDataSet("StoredProcName", ParameterValues);
如果Connection是OleDb,ODBC等,则无关紧要。第一行代码中的ConnectionStringName只是.config文件中定义的Consternating的名称。 您传递一个连接string名称,存储过程名称,以及组成参数的对象数组。 这只是可用的许多甜蜜function之一。
你会得到你想要build立的一切,然后一些。
官方网站是: http : //msdn.microsoft.com/en-us/library/ff648951.aspx
为了节省您的一些search,数据类文档可以在这里find: http : //msdn.microsoft.com/en-us/library/microsoft.practices.enterpriselibrary.data(PandP.50).aspx
(而且它是免费的,并定期更新。)
您的Parameters
参数需要是IDataParameter[]
types,并且给定错误文本,具体实现需要是SqlParameter[]
types。
如果你想保留你的签名,你需要一个工厂来获得必要的具体实现。
using System.Data.SqlClient;
添加using System.Data.SqlClient;
和cmd.Parameters.Add(new SqlParameter("@parameterName", value));
这个答案是为了比你所做的稍微更具体的目的,但build立在@Dismissile的答案,我用一个Dictionary
来提供参数名称和值在我的个人项目中的foreach
循环。
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); } }