SqlDataReader中的类型转换问题

4
假设我有这个 SQL 语句,并且已经执行了一个 SQL 命令来获取一个数据读取器:
"select 1 union select 2"
//.....
var rdr = cmd.ExecuteReader();

现在我想要读取第一行第一列的值:

var myInt = (int)rdr.GetValue(0); //great this works
var myLong = (long)rdr.GetValue(0); //throws cast exception, even though you can cast int to long

看起来在C#中,你需要精确匹配SQL类型进行转换。例如,如果SQL类型是bigint,则只能转换为long。如果SQL类型是int,则只能转换为int。不允许混合使用。
我想要的是无论C#请求和SQL返回的整数类型如何,只要理论上可以将一个类型转换为另一个类型,就能得到可行的结果。所以,如果SQL Server给我一个浮点类型,而我要求一个整型,我想要从执行这个转换得到的截断整数。
我的目标是使这个函数适用于泛型,这样当泛型参数与SQL Server中的数据类型不完全匹配时,该函数也能够工作。
List<T> GetFirstColumn<T>(string sql) where T : struct
{
    //get connection, execute reader
    // loop: 
    //    lst.Add(  (T) rdr.GetValue(0));
}

我希望这适用于两个语句:

var sql1 = "Select 1"; //sql int
var sql2 = "Select cast(1 as bigint)"; //sql equivalent of a long
var lst1 = GetFirstColumn<int>(sql1);
var lst2 = GetFirstColumn<int>(sql2);

有没有相对简单的方法来完成这个任务?
3个回答

5

正如Fredrik所说,SqlDataReader中的值是装箱的。你可以使用Convert.ToInt32将装箱的值转换为int,例如:

int i = Convert.ToInt32(read[0]);

即使SQL Server返回bigint或decimal类型,此方法也会尝试进行转换。


4

System.Convert会负责转换。

T GetValue<T>(SqlDataReader rdr)
{
    var dbVal = rdr.GetValue(0);
    var csVal = (T)System.Convert.ChangeType(dbVal, typeof(T));
}

注意:如果 T == Nullable<S>,则需要使用反射进行一些额外的工作,以获取底层类型并调用具有 typeof(S) 作为类型参数的 ChangeType。显然,微软没有在 .NET 2.0 和可空类型引入时更新 ChangeType 函数。如果它是可空类型,并且 dbVal is DBNull,则可以返回 null。
object dbValue = 5;

//this throws
Convert.ChangeType(dbValue, typeof(int?));

//this works
if(dbValue == DBNull.Value || dbValue == null) 
{
  if(typeof(int?).IsNullable) //or is a class, like string
  {return null;}

  dbValue = null;
}

var type = GetUnderlyingType<int?>(); //== typeof(int)
Convert.ChangeType(dbValue, type);

3
我认为你的问题在于GetValue返回一个object。这意味着对于一个int,你将得到一个封装在object中的int。然后你不能直接将其转换为long,而必须首先将其解包为int
var myLong = (long)(int)rdr.GetValue(0);

使用泛型来完成这个任务可能会比较棘手。你可以创建一个有两个类型参数的泛型方法,其中一个指定字段的类型,另一个指定你想要的类型。但我并不认为这是必要的;SqlDataReader已经有了各种数据类型的方法,例如GetInt32GetInt64等等,因此在这种情况下,泛型方法并没有真正提供任何附加值。


目的是能够从C#中调用它,而不必关心SQL Server类型是什么,只要它可以转换即可。 - dan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接