【问题标题】:Best practice to check if DataRow contains a certain column检查 DataRow 是否包含特定列的最佳实践
【发布时间】:2013-08-15 00:33:14
【问题描述】:

目前,当我遍历 DataRow 实例时,我会这样做。

foreach(DataRow row in table)
  return yield new Thingy { Name = row["hazaa"] };

迟早(即早),我会让 table 缺少列 donkey 并且便便会撞到风扇。经过一番广泛的谷歌搜索(大约 30 秒),我发现了以下保护语法。

foreach(DataRow row in table)
  if(row.Table.Columns.Contains("donkey"))
    return yield new Thingy { Name = row["hazaa"] };
  else
    return null;

现在 - 这是最简单的语法吗?!真的吗?我期待有一种方法可以让我获得该字段(如果存在)或 null 否则。或者至少在 row 上直接有一个 Contains 方法。

我错过了什么吗?我会以这种方式在许多领域进行映射,因此代码看起来非常不可读......

【问题讨论】:

    标签: c# dataset


    【解决方案1】:

    由于您的 DataTable 表始终具有相同的列(它们不会因任何行而改变),您只需检查一次列名。

    if (table.Columns.Contains("donkey"))
    {
        foreach ...
    }
    

    【讨论】:

    • 这对一栏来说很好,但是,正如操作所说,最终会有很多栏,所以如果你不知道哪些可能存在哪些可能不存在,你将如何管理它们?
    • @Varun,我肯定不会保留固定字符串。如果hazaa 列不存在了,你会怎么做?
    • @Heslacher 这就是重点。我需要管理该专栏有时会出现,有时不会出现。我无法控制它,但我仍然需要管理它。您的示例为单个列分叉,并且可以推断为多个。但是,请注意,问题是除了您提供的 via table 之外,是否还有用于检查的语法。
    【解决方案2】:

    你可以创建一个扩展方法让它更干净:

    static class DataRowExtensions
    {
        public static object GetValue(this DataRow row, string column)
        {
            return row.Table.Columns.Contains(column) ? row[column] : null;
        }
    }
    

    现在这样称呼它:

    foreach(DataRow row in table)
        return yield new Thingy { Name = row.GetValue("hazaa") };
    

    【讨论】:

    • 这是一个不错的解决方案。不知道为什么它没有得到更多的支持。无论如何,我要 +1。
    • 哇!一个非常整洁的解决方案。谢谢!
    • 不错的一个!但是,在野外实施时,它还应该检查 rowcolumn 是否为正常值。
    【解决方案3】:
    foreach (DataColumn item in row.Table.Columns)
    {
        switch (item.ColumnName)
        {
            case "ID":
                {
                    p.ID = Convert.ToInt32(row[item.ColumnName].ToString());
                }
                break;
            case "firstName":
                {
                    p.firstName = row[item.ColumnName].ToString();
                }
                break;
            case "lastName":
                {
                    p.lastName = row[item.ColumnName].ToString();
                }
                break;
    
            default:
                break;
        };
    }
    

    【讨论】:

    • 这实际上非常适合我的需要。 (我不喜欢它,但我认为我不能做得更好......)
    【解决方案4】:

    要基于 Varun K 的答案,请使用泛型类型参数:

    public static T GetValue<T>(this DataRow row, string column)
    {
        if (!row.Table.Columns.Contains(column))
            return default(T);
    
        object value = row[ColumnName];
        if (value == DBNull.Value)
            return default(T);
        return (T)value;
    }
    

    【讨论】:

      【解决方案5】:

      有时可能存在列名,但行不包含该列的数据;例如,在使用 ReadXML 填充 DataTable 之后。

      一个简单、快速和安全的解决方案是使用类型检查:

      if(row["columnname"].GetType() != typeof(System.DBNull)){
          //DataRow contains "columname"
      }else{
          //a safe scope to set default cell data
      }
      

      【讨论】:

      • 我发现这个问题仍然得到了新的答案、点赞和 cmets,这让我很兴奋。鉴于自从被询问(并回答)以来已经过去了整整 7 年,我想知道用户是如何在搜索中得到它的。既然有人问过,我认为 EF 接管并与 Dapper 和 nHybernate 一起消除了它的相关性。你是怎么碰巧碰到它的? (另外,+1 可以换个角度。)
      【解决方案6】:

      我真的很喜欢@Varun K 采用的方法。因此,以此为出发点,我只想投入两分钱,以防它对其他人有所帮助。我只是对其进行了改进,使其成为 generic 而不仅仅是使用 object 作为返回类型。

      static class Extensions
      {
        public static T Get<T>(this DataRow self, string column)
        {
          return self.Table.Columns.Contains(column)
            ? (T)self[column]
            : default(T);
          }
        }
      }
      

      【讨论】:

      • 应在信用到期的地方提供信用。但是你的答案是一个很大的改进,我选择重新接受它作为新的正确答案。我还冒昧地通过将名称更改为更抽象的名称来稍微适应它的通用性质。我希望没问题。
      • 感谢您阐明学分应该在哪里。此外,我非常感谢您冒昧地使该方法变得更好。我相信这就是想法。获得代码的所有权并尝试让每一次都变得更好。
      • 这可能会导致误导性结果,例如,如果您尝试从不存在的列中获取整数值。该方法将返回 0,这可能会导致某人相信该列存在并且该字段包含有效值 0。
      猜你喜欢
      • 1970-01-01
      • 2011-12-23
      • 2014-06-12
      • 1970-01-01
      • 2016-07-02
      • 1970-01-01
      • 2014-05-24
      • 2019-10-28
      相关资源
      最近更新 更多