【问题标题】:Pros and Cons of using "as", "is", "DBNull", ToString() in C#在 C# 中使用“as”、“is”、“DBNull”、ToString() 的优缺点
【发布时间】:2011-12-06 01:43:12
【问题描述】:

从 ExecuteReader 读取数据时。它在 IDataReader 中向我返回数据。当我想将此数据填充到我的实体中时,我将在大多数情况下将非 Nullable 值分配给 Nullable 类型或 Non Nullable 类型,例如:

int id;
string name;
int? age;
byte[] image;

example e = new example();
e.id = (int)dr["id"]; //unbox
e.name = dr["name"].ToString() //will result in empty string if dr["name"] is DBNull
e.name = dr["name"] is DBNull ? null : dr["name"].ToString();
e.age = dr["age"] as int?; // way 1
e.age = dr["age"] is DBNull ? null : (int?)dr["age"]; //way 2
e.image = dr["image"] as byte?;

编辑

如果 id 是表的主键并且是 NonNullable。但是它正在另一个表中使用,其中该键可能是NULL,那么应该采用什么方法。如果该实体变为 NULL 或应该抛出异常。

【问题讨论】:

  • 顺便说一句...根据我所见,这对于dapper-dot-net 来说是完美Query<example>(sql, args) 将为您完成所有这些工作,经过优化、缓存并且没有拼写错误/大量代码的风险。
  • @MarcGravell:请在您的评论中添加更多信息,如果我没记错的话,此函数将在内部映射到 DAL 中的示例实体。如果是这样,我正在使用相同的做法,只是为了获得更好的方法,这是我认为呈现的最简单的方法。
  • @vaibhav - 现在的生命太短,无法手动从数据库映射到实体。

标签: c# .net ado.net


【解决方案1】:

如果对象引用为 null,则 is 运算符始终返回 false,因为没有可用于检查其类型的对象。

if (o is Employee) {
Employee e = (Employee) o;
// Use e within the ‘if’ statement.
}

as 运算符的工作方式与强制转换类似,但 as 运算符永远不会抛出异常。相反,如果无法转换对象,则结果为 null。

Employee e = o as Employee;
if (e != null) {
// Use e within the ‘if’ statement.
}

查看更多:C# is and as operators

【讨论】:

【解决方案2】:

如果您确定结果类型并且不能为空:

(int)dr["id"]

如果结果可以为空并且你知道类型:

dr["age"] as int?;
dr["age"] as int? ?? -1; // default value

如果结果不能为空并且你不知道类型:

Convert.ToInt32(dr["age"]);

如果结果可以为空并且你不知道类型:

object age = dr["age"]; // can be short, int, etc
!Convert.IsDBNull(age) ? Convert.ToInt32(age) : -1;

【讨论】:

    【解决方案3】:

    我的作业如下所示:

    e.id    = (int)dr["id"]; //unbox
    e.name  = dr["name"]  as string; // String if string, null if DbNull
    e.age   = dr["age"]   as int?;
    e.image = dr["image"] as byte?;
    

    as 运算符最适用于引用类型(例如字符串或可空对象),因为如果我要转换的对象是其他对象(例如 DbNull),它将返回 null。这与手动检查完全相同,但更简洁易懂。

    【讨论】:

      【解决方案4】:

      查看this question 的答案,了解一些针对您的问题的通用帮助函数的良好示例。

      【讨论】:

        【解决方案5】:

        在 (cmets) 中,您询问了有关我简洁评论的更多信息;我试图说明的一点是,这本质上是一个已解决的问题,这里有一系列工具可以提供帮助,从复杂且功能丰富的 ORM(NHibernate、实体框架、LLBLGenPro)到中间立场(LINQ -to-SQL 等),到极其简单(但非常有效)的微 ORM(dapper-dot-net、Peta.Poco、Simple.Data)。

        dapper-dot-net 是支持 stackoverflow/stackexchange 的(免费提供,OSS)微 ORM。它基于直接从返回的列名映射到成员名(字段或属性)的极其简单的方法,因此用法很简单:

        var connection = ... // an open connection
        int id = ...  // a record to fetch
        var singleItem = connection.Query<example>(
            "select * from example where id = @id", new {id}).Single();
        

        int customerId = ...
        var orders = connection.Query<Order>(
            "select * from Orders where Status = 'Open' and CustomerId = @customerId",
            new {customerId}).ToList();
        

        其中example 是代码中的类型,成员为nameid 等。它负责所有繁重的工作:

        • 将输入映射到参数(请参阅@id@customerId,以及如何提供它们的值)
        • 以非常优化的方式将返回的记录具体化为对象
        • 其他一些技巧,例如水平多重映射、多重网格映射、自动IN 处理等

        这意味着您不必担心nullDBNullNullable&lt;T&gt; 等细节,因为 dapper 已经为您处理了所有这些,并且是(感谢一些 IL voodoo)在运行时与自己编写具体化代码一样快。

        【讨论】:

          猜你喜欢
          • 2011-01-27
          • 2022-12-22
          • 1970-01-01
          • 2011-11-03
          • 1970-01-01
          • 2015-05-05
          • 1970-01-01
          • 2013-12-02
          • 2011-01-07
          相关资源
          最近更新 更多