【发布时间】:2016-12-21 18:21:53
【问题描述】:
最近,我们遇到了以下问题:
简而言之:myCommand.Parameters.AddWithValue("@SomeParameter", DBNull.Value); 显然将 DBNull 参数“类型化”为 nvarchar,它可以隐式转换为几乎所有其他类型,但不幸的是,不是 varbinary,从而产生以下错误:
不允许从数据类型 nvarchar 到 varbinary(max) 的隐式转换。使用 CONVERT 函数运行此查询。
不幸的是,链接问题中建议的解决方案不适用,因为我们在数据访问库的深处使用AddWithValue,该库旨在从参数类型推断数据类型并且不支持添加“真实”SQL服务器类型。
我通过将 DBNull 参数显式键入为 ints 来“修复”了这个问题:
void MyImprovedAddWithValue(SqlCommand cmd, string key, object value)
{
if (value == DBNull.Value)
{
cmd.Parameters.Add(key, SqlDbType.Int).Value = DBNull.Value;
}
else
{
cmd.Parameters.AddWithValue(key, value);
}
}
这似乎有效。显然,类型为 int 的 NULL 可以隐式转换为 SQL Server 支持的任何其他类型。
忽略AddWithValue has some well-known shortcomings(我们非常清楚)这一事实,使用这种方法是否会出现任何问题? SqlParameterCollection.AddWithValue 的设计者是否有充分的理由不“默认”这样做,而我忽略了这一点?
【问题讨论】:
-
AddWithValue 与 DBNULL 配合使用效果很好,当 value == null 时会出现问题
-
我建议您完全避免 AddWithValue 并明确指定参数的正确类型。这不仅可以避免意外,还可以在某些情况下显着提高性能。
-
当您在顶级代码中构造参数时,这一切都很好,但对于在提取层深处构造 SqlParameters 的框架或 API 来说没有多大意义。跨度>
-
@MikhailLobanov:当目标数据类型为 varbinary 时不会,请参阅链接问题。
-
@DanGuzman:我同意,这就是我们下次完全重写数据访问层时要做的事情。已经吸取了教训。目前,我们有大量的遗留代码不提供正确的参数类型,并且没有计划在短期内重写。
标签: c# sql-server ado.net