首先,让我解释一下当前的情况:我正在从数据库中读取记录并将它们放入一个对象中以备后用;今天有一个关于数据库类型到C#类型转换(强制转换?)的问题出现了。
让我们看一个例子:
namespace Test
{
using System;
using System.Data;
using System.Data.SqlClient;
public enum MyEnum
{
FirstValue = 1,
SecondValue = 2
}
public class MyObject
{
private String field_a;
private Byte field_b;
private MyEnum field_c;
public MyObject(Int32 object_id)
{
using (SqlConnection connection = new SqlConnection("connection_string"))
{
connection.Open();
using (SqlCommand command = connection.CreateCommand())
{
command.CommandText = "sql_query";
using (SqlDataReader reader = command.ExecuteReader(CommandBehavior.SingleRow))
{
reader.Read();
this.field_a = reader["field_a"];
this.field_b = reader["field_b"];
this.field_c = reader["field_c"];
}
}
}
}
}
}
显然,这个代码失败了,因为三个this.field_x = reader["field_x"];
的调用会抛出Cannot implicitly convert type 'object' to 'xxx'. An explicit conversion exists (are you missing a cast?)
编译器错误。
为了纠正这个问题,我目前知道两种方法(让我们使用field_b
作为例子):第一种是this.field_b = (Byte) reader["field_b"];
,第二种是this.field_b = Convert.ToByte(reader["field_b"]);
。
第一种方法的问题在于,DBNull
字段会抛出异常,因为强制转换失败(即使是可空类型如String
),而第二种方法的问题在于它不能保留空值(Convert.ToString(DBNull)
会产生一个String.Empty
),并且我也不能将其用于枚举类型。
因此,在互联网上和StackOverflow上查找了一些资料后,我想到了以下解决方案:
public static class Utilities
{
public static T FromDatabase<T>(Object value) where T: IConvertible
{
if (typeof(T).IsEnum == false)
{
if (value == null || Convert.IsDBNull(value) == true)
{
return default(T);
}
else
{
return (T) Convert.ChangeType(value, typeof(T));
}
}
else
{
if (Enum.IsDefined(typeof(T), value) == false)
{
throw new ArgumentOutOfRangeException();
}
return (T) Enum.ToObject(typeof(T), value);
}
}
}
我应该处理每种情况。
问题是:我有什么遗漏吗?我是否在浪费金钱、时间和精力(WOMBAT),因为有更快更简洁的方法?这一切都正确吗?盈利?