假设我有一个像这样的自定义类:
public class Customer
{
public int CustomerID { get; set; }
public string CompanyName { get; set; }
public string BusinessAddress { get; set; }
public string Phone { get; set; }
public int ParentID { get; set; }
}
我使用datareader从数据库创建自定义对象。例如:
while (dr.Read())
{
listCustomers.Add(new Customer(
Convert.ToInt32(dr["CustomerID"]),
Convert.ToString(dr["CompanyName"]),
Convert.ToString(dr["BusinessAddress"]),
Convert.ToString(dr["Phone"]),
Convert.ToInt32(dr["ParentID"]),
)
在数据库中ParentID可以为null(我无法更改它)。当它为null时,转换显然会失败。
我应该如何处理从数据库中检索的空值以填充我的业务对象?在我的自定义类中使用Nullable Types会不会很好?还有其他提示吗?
答案 0 :(得分:6)
绝对。可空类型非常好。否则,你必须提出一些愚蠢的约定a-la“当ParentID为-1时,这意味着Customer
没有父”。可空类型强制执行“按设计”:如果没有父级,ParentID
将为null
。
至于保护对象,请考虑使用ORM工具(例如NHibernate或BLToolkit),因为您实际上并不想花费50%的开发时间来编写SQL查询并填充来自数据阅读器的对象
答案 1 :(得分:3)
在业务对象中使用可空类型。然后,您可以使用这样的通用帮助器方法从数据库中提取可空字段。
public static T? GetValue<T>(IDataRecord record, string columnName)
where T : struct
{
int columnIndex = record.GetOrdinal(columnName);
if (record.IsDBNull(columnIndex))
return null;
else
return (T)Convert.ChangeType(record[columnIndex], typeof(T));
}
因此,如果ParentId
被声明为int?
,则在加载行时会执行以下操作。
obj.ParentId = GetValue<int>(dr, "ParentId");
答案 2 :(得分:2)
如何添加这样的助手:
static string safeGetStringFromDB( IDataReader dr, string strField )
{
int nIndex = dr.GetOrdinal( strField );
if ( dr.IsDBNull( nIndex ) )
return string.Empty;
return dr.GetString( nIndex );
}
答案 3 :(得分:2)
Nullable类型适用于可空字段。
使用三元组处理作业: -
ParentID = ( dr["ParentID"] is DBNull ) ? null : (int)dr["ParentID"];
此外,如果您知道底层数据库字段及其.NET表示形式,则无需使用Convert。
我将转换的使用限制在的情况下,我知道类型不同(比如说int到string)。
当我知道.NET对应的类型时,我只会演员: -
listCustomers.Add(new Customer(
(int)dr["CustomerID"],
(string)dr["CompanyName"],
(string)dr["BusinessAddress"],
(string)dr["Phone"],
( dr["ParentID"] is DBNull ) ? null : (int)dr["ParentID"]));
最后,在使用可空类型时,请注意重载方法可能是一个潜在的问题。
考虑以下示例: -
public void Populate( int? facilityId, string name, bool? somethingElse )...
public void Populate( string facilityCode, string name, bool? somethingElse )...
相同数量的参数,所有参数都可能为空。当第一个参数为null时,您可能会对编译器最终选择的解释感到惊讶。无论如何,之前已经抓住了我。
答案 4 :(得分:1)
您可以创建这样的帮助方法:
static T Map<T>(object obj, Func<object, T> map, T def)
{
if (obj != null)
{
return map(obj);
}
return def;
}
static T Map<T>(object obj, Func<object, T> map)
{
return Map<T>(obj, map, default(T));
}
并使用它们:
object o = 1;
var t = Map(o, Convert.ToInt32, 0); // with default value
var t2 = Map(o, Convert.ToInt32); // or without default value
答案 5 :(得分:0)
ParentID是您班级中的一个字符串,您将其转换为Int32。
但是,除此之外:您知道数据库,因此您知道哪些字段可以为null。我也会在数据对象中使所有这些字段都可以为空,因为在我看来,这是尽可能接近地建模数据库的最佳方法。