【发布时间】:2012-01-04 07:39:20
【问题描述】:
我正在创建一个小的帮助函数来返回 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 只接受非空的 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;
}
感谢您的想法/链接等:)
【问题讨论】:
-
Parameters.GetValue 有什么作用?
-
不错的实际解决方案。但是,在 MS Access/OleDb 中将 DateTime.Now 设置为 DateTime 字段失败。
-
我听说避免日期时间错误的解决方案是将毫秒设置为零,这将解决数据类型不匹配错误。真的吗? (我现在关心 MS Access 和 SQL Server)。