来自SqlDataReader的转换问题

时间:2010-09-03 22:13:44

标签: c# sql-server ado.net

假设我有这个sql语句并且我已经执行了一个sql命令来获取一个datareader:

"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类型完全匹配。 I.E.如果sql类型是bigint,则只能转换为long。如果sql类型是int,则只能转换为int。没有混搭......

我只是想得到一些有效的东西,无论整数c#的类型是什么,并且sql返回,只要你理论上可以将一个转换为另一个。因此,如果SQL Server给我一个浮点类型,并且我要求一个int,我想要你做的那个截断的int。

我的目标是使用泛型工作,所以当泛型参数与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 个答案:

答案 0 :(得分: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。显然,MS没有使用.NET 2.0更新ChangeType函数并引入了nullables。如果它是可空的,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);

答案 1 :(得分:4)

就像Fredrik所说,来自SqlDataReader的值是盒装的。您可以使用int将带框值转换为Convert.ToInt32,例如:

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

即使SQL Server返回bigint或小数,也会尝试转换。

答案 2 :(得分:3)

我认为您的问题是GetValue会返回object。这意味着,如果是int,您将在int中获得一个object框。然后,您无法直接将其转换为long,但必须先将其解压缩为int

var myLong = (long)(int)rdr.GetValue(0);

我会说,使用泛型这将非常棘手。好吧,你可以制作带有两个类型参数的泛型方法;一个指定字段的类型,另一个指定所需的类型。但我真的没有看到需要; SqlDataReader已经有各种数据类型的方法,例如GetInt32GetInt64等等,因此在这种情况下,泛型方法实际上不会给出任何附加值。

相关问题