[英]InvalidCastException long to ulong
我有以下方法:
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"}
為什么
您只能將值類型取消裝入其原始類型。 在你的情況下,演員首先需要從object
轉到long
然后再到ulong
。
有關詳細信息,請參閱此問題:
它還鏈接了Eric Lippert的博客文章 。
怎么樣
如你所知,一種方法是在轉換為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);
亞當的答案正確地確定了問題; 這是一個解決方案:只要可以使用內置或自定義轉換將其轉換為T
,您可以使用LINQ取消任何類型的轉換。
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來提高此類轉換的效率。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.