我有以下方法:
public static T ExecuteScalar<T>(
string query,
SqlConnection connection,
params SqlParameter[] parameters) where T : new()
{
// Create SqlCommand
SqlCommand command = CreateCommand(query, connection, parameters);
// Execute command using ExecuteScalar
object result = command.ExecuteScalar();
// Return value as expected type
if (result == null || result is DBNull) return default(T);
return (T)result;
}我想把数据库的MIN_ACTIVE_ROWVERSION作为ulong。奇怪的是..。下面的第一个方法调用会生成一个错误,但是第二个方法调用可以正常工作。
方法调用1生成一个错误:
ulong minActiveRowversion =
SqlUtils.ExecuteScalar<ulong>(
"SELECT CAST(MIN_ACTIVE_ROWVERSION() AS BIGINT)"
, _connectionString);错误:
System.InvalidCastException: Specified cast is not valid.方法调用2运行良好:
ulong minActiveRowversion =
(ulong)SqlUtils.ExecuteScalar<long>(
"SELECT CAST(MIN_ACTIVE_ROWVERSION() AS BIGINT)"
, _connectionString);我不明白这怎么可能,因为command.ExecuteScalar()方法的结果是:
object result | 1955612
result.GetType() | {Name = "Int64" FullName = "System.Int64"}发布于 2012-06-27 12:42:25
为什么
您只能将值类型解压缩为其原始类型。在您的例子中,强制转换首先需要从object转到object,然后再转到ulong。
有关更多细节,请参见此问题:
它还链接了Eric的一个博客帖子。
How
如您所知,一种方法是在转换为T之前先转换为原始类型--当然,除非原始类型是T。
正如注释中提到的,另一种方法是使用转换例程(Convert.ToUInt64),而不是显式转换。
这可能通过使用Func<object, T>来实现。
public static T ExecuteScalar<T>(
Func<object, T> conversionFunctor,
string query,
SqlConnection connection,
params SqlParameter[] parameters) where T : new()
{
// Create SqlCommand
SqlCommand command = CreateCommand(query, connection, parameters);
// Execute command using ExecuteScalar
object result = command.ExecuteScalar();
// Return value as expected type
if (result == null || result is DBNull)
return default(T);
return conversionFunctor(result);
}打电话:
ulong minActiveRowversion =
SqlUtils.ExecuteScalar<ulong>(
Convert.ToUInt64,
"SELECT CAST(MIN_ACTIVE_ROWVERSION() AS BIGINT)"
, _connectionString);发布于 2012-06-27 13:01:24
Adam的回答正确地识别了问题;这里有一个解决方案:您可以使用LINQ任何类型,只要它可以通过内置或自定义转换转换到T。
static T UnboxUnchecked<T>(object obj) {
var pe = Expression.Parameter(typeof(object));
return Expression.Lambda<Func<object,T>>(
Expression.Convert(
Expression.Convert(pe, obj.GetType())
, typeof (T)
)
, pe
).Compile()(obj);
}此方法生成一个LINQ表达式,该表达式首先将对象解压缩为其实际类型,然后应用转换。替换方法的最后一行
return (T)result;使用
return UnboxUnchecked<T>(result);让它发挥作用。
下面是一篇文章的链接,它解释了如何通过缓存已编译的lambda来提高这类转换的效率。
https://stackoverflow.com/questions/11226448
复制相似问题