65.9K
CodeProject 正在变化。 阅读更多。
Home

检查 DataTable 中是否存在可选列

starIconstarIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIcon

2.89/5 (13投票s)

2004 年 10 月 10 日

2分钟阅读

viewsIcon

75800

downloadIcon

2

检查 DataTable 或 DataSet 中是否存在可选数据元素的方法。

Sample Image - DataException.gif

引言

本文讨论了检查 DataTable 中是否存在可选列的方法。 访问可选列可能比较棘手,因为尝试访问不存在的列(或 DataSet 中不存在的 DataTable)会引发异常。

背景

在处理外部或动态数据时,您永远无法确定 DataRow 中将存在哪些列,以及该 DataTable 是否将存在于 DataSet 中。 我经常使用 DataSet.ReadXML() 方法将 XML 文件读入 DataSet。 我遇到的最常见的问题是一些 XML 元素和属性是可选的。 缺少可选元素可能会导致表不存在(因为 ReadXml() 将每个元素映射到一个表)。 不存在的可选属性可能会导致与包含元素对应的表中缺少列。

“可选”数据列的另一个来源是数据库架构版本和更改。 开发环境中使用的数据库架构可能包含生产数据库架构中不存在的列。 健壮的代码应该能够应对小的架构差异并处理丢失的数据列。

简单的方法

访问缺少的元素会引发异常——没问题,我可以简单地用一个空的 try-catch 块包围代码并忽略该异常,对吗?

private void ReadingSomeData(DataTable dt)
{
    foreach (DataRow dr in dt.Rows)
    {
        …
        // Read optional data
        int myOptionalData = -1; // or whatever default makes sense
        try
        {
            myOptionalData = Convert.ToInt32(dr[“MyOptionalColumn”]);
        }
        catch {}
        …
        (General exception handling here)
    }
}

看起来不错,对吗? 使用“try-catch”方法进行测试有两个基本问题

  • 抛出和捕获异常是缓慢的
  • 真正的异常(例如错误的数据格式)被屏蔽了。

例如:如果我们的可选数据实际上存在,但包含的是 string 而不是 int,则 Convert.ToInt32() 引发的异常将被忽略,您可能永远不会意识到该问题。

根据我的经验,除非出于非常好的(而且非常具体)的原因,否则忽略异常是不好的。

优雅的方法

DataSetDataTable 都支持 Contains() 方法。 使用 Contains() 检查是否存在可选元素。 使用 Contains() 方法,异常不会被屏蔽,如果数据有问题,问题就会变得明显。

上面的例子变成了

private void ReadingSomeData(DataTable dt)
{
    foreach (DataRow dr in dt.Rows)
    {
        …
        // Read optional data
        int myOptionalData = -1; // or whatever default makes sense
        if (dt.Columns.Contains(“MyOptionalColumn”)
        {
            myOptionalData = Convert.ToInt32(dr[“MyOptionalColumn”]);
        }
        …
        (General exception handling here)
    }
}

好多了,但是如果您只有 DataRow 可以使用怎么办? 将整个 DataTable 拖到方法中似乎很可惜! 不用担心,您可以使用 DataRowTable 属性访问 DataRow 父级 DataTable

private void ReadMyDataRow(DataRow dr)
{
    …
    // Read optional data
    int myOptionalData = -1; // or whatever default makes sense
    if (dr.Table.Columns.Contains(“MyOptionalColumn”)
    {
        myOptionalData = Convert.ToInt32(dr[“MyOptionalColumn”]);
    }
    …
    (General exception handling here)
}

那可选表呢? 没问题……

private void ReadMyDS(DataSet ds)
{
    …
    // Check for an optional table
    if (ds.Contains(“MyNewTable”))
    {
        ReadingSomeData(ds.Tables[“MyNewTable”])
        …
    }
    …
    (General exception handling here)
}

结论

外部数据永远不是 100% 可预测的。 使用 Contains() 方法优雅而健壮地处理可选数据元素,而不会掩盖实际的数据问题。

历史

V1.0 - 原始发布。

© . All rights reserved.