我有一些(不止一点)代码,其中将来自 DataReader 的对象值分配给业务对象属性。这段代码看起来非常凌乱,有很多空合并、解析等。我想知道如何实现一种更简洁的方法,将对象值从 DataReader 转换为对象属性的适当值。
一个选项是为每种数据类型设置离散的转换函数,其中我的对象属性上的数据类型仅限于一小组 CLR 基元类型。我不使用可为 null 的类型,因为那时我只是将不整洁的地方移到其他地方使用这些值的地方。
我的第二个选择是为所用的四种左右数据类型中的每一种创建一个扩展方法,仅限于发生这些分配的特定命名空间。像这个相当简单的例子:
public static void SafelyAssign(this string target, object value)
{
if (value is string)
{
target = (string)value ?? "";
}
else
{
target = value.ToString();
}
}
我还有哪些其他选择?
我喜欢的解决方案是从 CSLA.Net 中采纳的框架。创建 SafeDataReader它实现了 IDataReader。我会尝试找到一个链接,但这里有一个如何获取安全整数的示例。这个解决方案不需要 CSLA.Net 框架,这就是他解决问题的方式,我觉得非常方便。
public class SafeDataReader : IDataReader, ISafeDataRecord
{
/// <summary>
/// Gets an integer from the datareader.
/// </summary>
/// <remarks>
/// Returns 0 for null.
/// </remarks>
public int GetInt32(string name)
{
return GetInt32(_dataReader.GetOrdinal(name));
}
/// <summary>
/// Gets an integer from the datareader.
/// </summary>
/// <remarks>
/// Returns 0 for null.
/// </remarks>
public int GetInt32(int i)
{
if (_dataReader.IsDBNull(i))
return 0;
else
return _dataReader.GetInt32(i);
}
public object this[string name]
{
get
{
object val = _dataReader[name];
if (DBNull.Value.Equals(val))
return null;
else
return val;
}
}
public Nullable<T> GetNullable<T>(string name) where T:struct
{
int index = _dataReader.GetOrdinal(name);
if (_dataReader.IsDBNull(index))
{
return null;
}
else
{
return new Nullable<T>((T)_dataReader[index]);
}
}
}
编辑:好的,那么我们如何使用这个安全的数据读取器?所以让我们假设我们有一个 cmd 对象,它是所有设置
using (SafeDataReader reader=new SafeDataReader(cmd.ExecuteDataReader())
{
//Assume MyColumn was null here, this will still work because
//since a string can be null
string myString=reader["MyColumn"];
//In this case myInt will be set to 0 if MyColumn is DBNull
int myInt=reader.GetInt("MyColumn");
}
虽然您也可以使用 GetNullable 方法,但这不是他的类(class)的一部分,而且我不确定它来自哪里,但它对我来说看起来是正确的。
这有多便携?好吧,因为它正在实现 IDataReader,所以它应该非常便携;并且只要调用代码不期望返回 DBNull.Value,就应该能够换入和换出。
我是一名优秀的程序员,十分优秀!