如何处理业务对象中的空值

时间:2009-10-06 10:26:05

标签: c# asp.net sql-server business-objects

假设我有一个像这样的自定义类:

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会不会很好?还有其他提示吗?

6 个答案:

答案 0 :(得分:6)

绝对。可空类型非常好。否则,你必须提出一些愚蠢的约定a-la“当ParentID为-1时,这意味着Customer没有父”。可空类型强制执行“按设计”:如果没有父级,ParentID将为null

至于保护对象,请考虑使用ORM工具(例如NHibernateBLToolkit),因为您实际上并不想花费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。我也会在数据对象中使所有这些字段都可以为空,因为在我看来,这是尽可能接近地建模数据库的最佳方法。