【问题标题】:Generic way of handling DBNull处理 DBNull 的通用方法
【发布时间】:2011-11-10 07:14:08
【问题描述】:

使用 SqlDataReader 时,我的代码中有很多此类逻辑 有没有更干净更通用的方法来处理这个问题?

 if (reader["VisitingAddressId"] != DBNull.Value)
 {
     visitingAddress = new Address()
     {
         AddressId = Convert.ToInt64(reader["VisitingAddressId"]),
         Address1 = reader["VisitingAddress"].ToString(),
         AddressType = AddressType.VisitingAddress,
         PostalCode = reader["VisitingPostal"].ToString(),
         PostalDistrict = reader["VisitingPostalDistrict"].ToString()
      };
  }

 if (reader["PostalAddressId"] != DBNull.Value)
 {
     postalAddress = new Address()
     {
         AddressId = Convert.ToInt64(reader["PostalAddressId"]),
         Address1 = reader["PostalAddress"].ToString(),
         AddressType = AddressType.PostalAddress,
         PostalCode = reader["PostalPostal"].ToString(),
         PostalDistrict = reader["PostalPostalDistrict"].ToString()
      };
  }

【问题讨论】:

    标签: c# sqldatareader


    【解决方案1】:

    我在数据服务类中有这些辅助方法(您可以将它们都设为静态):

        public T CastDBValue<T>(object value)
        {
            return MapValue<T>(value);
        }   
    
        internal static T MapValue<T>(object value)
        {
            try
            {
                T result;
                result = value == DBNull.Value ? default(T) : (T)value;
                return result;
            }
            catch (InvalidCastException cex)
            {
                logger.ErrorFormat("Invalid cast while mapping db value '{0}' to type {1}. Error: {2}", value, typeof(T).Name, cex);
                throw new InvalidCastException(string.Format("Invalid cast while mapping db value '{0}' to type {1}. Error: {2}", value, typeof(T).Name, cex.Message));
            }
        }
    

    然后在您的映射代码中,您只需:

    AddressId = dataService.CastDBValue<int>(reader["AddressId"]));
    if (AddressId > 0) { ... }
    

    【讨论】:

    • 这正是我想要的。谢谢!
    【解决方案2】:

    您可以使用像 Dapper 这样的微 ORM:http://code.google.com/p/dapper-dot-net/

    多重映射功能将消除所有样板代码。

    db.Query<Post,Address,Address,Post>("select * from Posts left join Address ... etc", 
     (post,vaddress,paddress) => 
      {
         post.VisitingAddress = vaddress; 
         post.PostalAddress = paddress; 
         return post; 
       });
    

    【讨论】:

    • @KierenJohnstone - 我不会真正将 Dapper 归类为 ORM。它更简单,并且可以在不改变语义的情况下干净地消除 OP 示例中的样板代码。
    • 好吧,“.NET 的简单对象映射器”负责处理 O 和 M,“Dapper 是一个可以放入项目中的单个文件,它将扩展您的 IDbConnection 接口”处理R(即 RDBMS):)
    • @KierenJohnstone - 当然,但在实践中,ORM 一词已经涵盖的不仅仅是将关系数据映射到对象。工作单元,实体生命周期管理等。但足够的挑剔:-)
    • 是的,对不起。我想我是说这是一个可能的答案,但并不是真正的“答案”
    【解决方案3】:

    您指的是ORM,其中有很多。 NHibernate、实体框架,甚至 ADO.NET(您已经在使用)都支持关系数据集,但在这种情况下,您通常必须使用 DataSet 或派生的强类型类。

    在此处查看 .NET 部分以获取列表:

    http://en.wikipedia.org/wiki/List_of_object-relational_mapping_software

    你有什么要求?也许我们可以缩小范围。

    【讨论】:

    • 我们已经在使用 EntityFramework,但在这种特定情况下,我们使用经典的 ADO.NET 来调用存储过程。我们在使用实体框架和存储过程加载相关对象时遇到了一些问题。
    猜你喜欢
    • 2010-09-06
    • 2012-09-12
    • 2015-12-27
    • 2017-11-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-09
    • 1970-01-01
    • 2011-01-26
    相关资源
    最近更新 更多