我正在创建一个小辅助函数来返回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只接受非null的SqlParameter类型对象,而不接受String对象。
代码落在了一行:
cmd.Parameters.Add(Parameters.GetValue(i));
有什么想法吗?
对上述代码的任何改进都表示赞赏。
实际解决方案:
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;
}
感谢您的想法/链接等。)
答案 0 :(得分:78)
我相信IDbCommand有一个CreateParameter()方法:
var parameter = command.CreateParameter();
parameter.ParameterName = "@SomeName";
parameter.Value = 1;
command.Parameters.Add(parameter);
答案 1 :(得分:23)
您可以将接受答案的代码添加到扩展方法中:
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);
}
}
答案 2 :(得分:2)
我知道这不是你所要求的,但我有一个更简单,更强大的解决方案。
Microsoft模式和实践库包括一个非常强大且易于使用的数据访问应用程序块。用于执行存储过程和返回数据集的示例如下所示:
object[] ParameterValues = new object[] {"1",DateTime.Now, 12, "Completed", txtNotes.Text};
Database db = DatabaseFactory.CreateDatabase("ConnectionStringName");
DataSet ds = = db.ExecuteDataSet("StoredProcName", ParameterValues);
连接是OleDb,ODBC等并不重要。第一行代码中的ConnectionStringName只是.config文件中定义的Consternating的名称。传入构成参数的连接字符串名称,存储过程名称和对象数组。 这只是众多甜蜜功能中的一个。
你将获得你想要建立的所有东西,然后是一些。
官方网站位于:http://msdn.microsoft.com/en-us/library/ff648951.aspx
为了节省一些搜索,可在此处找到数据类文档:http://msdn.microsoft.com/en-us/library/microsoft.practices.enterpriselibrary.data(PandP.50).aspx
(它从Microsoft免费获得,并定期更新。)
答案 3 :(得分:0)
您的Parameters
参数必须是IDataParameter[]
类型,并且在给定错误文本的情况下,具体实现需要为SqlParameter[]
类型。
如果您希望保留签名,您需要一家工厂来获得必要的具体实施。
答案 4 :(得分:0)
这个答案仅用于比您正在做的更具体的目的,但建立在 @Dismissile 的答案之后,我使用1
2
3
4
来提供参数名称和值到我个人项目中的Dictionary
循环。
foreach
答案 5 :(得分:-2)
添加using System.Data.SqlClient;
和
cmd.Parameters.Add(new SqlParameter("@parameterName", value));