首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >InvalidCastException long to ulong

InvalidCastException long to ulong
EN

Stack Overflow用户
提问于 2012-06-27 12:40:22
回答 2查看 1.9K关注 0票数 6

我有以下方法:

代码语言:javascript
复制
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生成一个错误:

代码语言:javascript
复制
ulong minActiveRowversion = 
    SqlUtils.ExecuteScalar<ulong>(
        "SELECT CAST(MIN_ACTIVE_ROWVERSION() AS BIGINT)"
        , _connectionString);

错误:

代码语言:javascript
复制
System.InvalidCastException: Specified cast is not valid.

方法调用2运行良好:

代码语言:javascript
复制
ulong minActiveRowversion = 
    (ulong)SqlUtils.ExecuteScalar<long>(
        "SELECT CAST(MIN_ACTIVE_ROWVERSION() AS BIGINT)"
        , _connectionString);

我不明白这怎么可能,因为command.ExecuteScalar()方法的结果是:

代码语言:javascript
复制
object result       | 1955612
result.GetType()    | {Name = "Int64" FullName = "System.Int64"}
  1. 有人能告诉我,为什么第一个场景是不可能的,第二个场景是可行的?
  2. 有人能告诉我如何解决,这样我就可以使用场景1。
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-06-27 12:42:25

为什么

您只能将值类型解压缩为其原始类型。在您的例子中,强制转换首先需要从object转到object,然后再转到ulong

有关更多细节,请参见此问题:

为什么我不能将整数解压缩为十进制呢?

它还链接了Eric的一个博客帖子

How

如您所知,一种方法是在转换为T之前先转换为原始类型--当然,除非原始类型是T

正如注释中提到的,另一种方法是使用转换例程(Convert.ToUInt64),而不是显式转换。

这可能通过使用Func<object, T>来实现。

代码语言:javascript
复制
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);
}

打电话:

代码语言:javascript
复制
ulong minActiveRowversion = 
    SqlUtils.ExecuteScalar<ulong>(
        Convert.ToUInt64,
        "SELECT CAST(MIN_ACTIVE_ROWVERSION() AS BIGINT)"
        , _connectionString);
票数 5
EN

Stack Overflow用户

发布于 2012-06-27 13:01:24

Adam的回答正确地识别了问题;这里有一个解决方案:您可以使用LINQ任何类型,只要它可以通过内置或自定义转换转换到T

代码语言:javascript
复制
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表达式,该表达式首先将对象解压缩为其实际类型,然后应用转换。替换方法的最后一行

代码语言:javascript
复制
return (T)result;

使用

代码语言:javascript
复制
return UnboxUnchecked<T>(result);

让它发挥作用。

下面是一篇文章的链接,它解释了如何通过缓存已编译的lambda来提高这类转换的效率。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11226448

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档