【问题标题】:How to handle null values in my business objects如何处理我的业务对象中的空值
【发布时间】:2010-12-04 05:32:00
【问题描述】:

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

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; } 
}

我使用数据读取器从数据库创建自定义对象。例如:

  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 在数据库中可以为空(我无法更改)。当它为空时,转换显然会失败。

我应该如何处理从数据库中检索到的空值来填充我的业务对象?在我的自定义类中使用 Nullable 类型会是一种很好的做法吗?还有其他提示吗?

【问题讨论】:

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


    【解决方案1】:

    当然。可空类型非常好。否则,您将不得不想出一些愚蠢的约定 a-la “当 ParentID 为 -1 时,这意味着 Customer 没有父级”。可空类型强制执行此“设计”:如果没有父级,ParentID 将是 null

    至于对对象进行水合,请考虑使用 ORM 工具(例如 NHibernateBLToolkit),因为您真的不想花费 50% 的开发时间来编写 SQL 查询并从数据中填充对象读者

    【讨论】:

      【解决方案2】:

      在您的业务对象中使用可为空的类型。然后,您可以使用这样的通用辅助方法从数据库中提取可为空的字段。

      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");
      

      【讨论】:

        【解决方案3】:

        如何添加这样的助手:

            static string safeGetStringFromDB( IDataReader dr, string strField )
            {
                int nIndex = dr.GetOrdinal( strField );
                if ( dr.IsDBNull( nIndex ) )
                    return string.Empty;
                return dr.GetString( nIndex );
            }
        

        【讨论】:

          【解决方案4】:

          可空类型适用于可空字段。

          用三元处理赋值:-

          ParentID = ( dr["ParentID"] is DBNull ) ? null : (int)dr["ParentID"];
          

          此外,如果您知道底层 db 字段是什么以及它们的 .NET 表示形式,则无需使用 Convert。

          我将使用 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 )...
          

          相同数量的参数,所有参数都可能为空。当第一个参数为空时,您可能会对编译器最终选择的解释感到惊讶。无论如何,我之前已经发现了我。

          【讨论】:

          • 谢谢!我认为最后一部分应该是(int?)dr["ParentID"]而不是(int)dr["ParentID"],否则编译器会报错。
          【解决方案5】:

          你可以创建这样的辅助方法:

                  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
          

          【讨论】:

            【解决方案6】:

            ParentID 是您班级中的一个字符串,您正在将其转换为 Int32。

            除此之外:您了解数据库,因此您知道哪些字段可以为空。我也会让数据对象中的所有这些字段都为空,因为在我看来,这是尽可能接近数据库建模的最佳方式。

            【讨论】:

              猜你喜欢
              • 2011-01-23
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2022-01-19
              • 1970-01-01
              • 1970-01-01
              • 2016-01-16
              • 1970-01-01
              相关资源
              最近更新 更多