如何检查数据表中是否存在某列

128

我有一个由CSV文件内容生成的数据表。我使用其他信息将CSV中的某些列(现在在数据表中)映射到用户需要填写的信息。

在最理想的情况下,映射应该总是可能的。但这不是现实...因此,在尝试映射数据表列值之前,我需要检查该列是否存在。如果我不进行此检查,就会出现参数异常。

当然,我可以使用类似以下的代码来检查:

try
{
    //try to map here.
}
catch (ArgumentException)
{ }

但是我目前有3列需要映射,其中一些或全部可能存在/缺失

有没有好的方法检查数据表中是否存在某列?


你正在处理一个DataSet/DataTable吗?如果是的话,你可以查看表中的列集合,以获取表中所有列的列表。 - asawyer
是的,@asawyer,CSV的内容被转储到数据表中。我会朝这个方向看一下。 - Rémi
8个回答

251

您可以使用Contains运算符

private void ContainColumn(string columnName, DataTable table)
{
    DataColumnCollection columns = table.Columns;        
    if (columns.Contains(columnName))
    {
       ....
    }
}

MSDN - DataColumnCollection.Contains()


你确定这是 LINQ 吗?我的代码中没有任何与 LINQ 相关的引用,但它确实可以工作。 - Rémi
它是列的简单运算符。 - Aghilas Yakoub
这不是一个 LINQ 扩展方法,而是 DataColumnCollection 类型的成员,但同样也可以很好地工作。 - asawyer
5
@AghilasYakoub 当然,我忘记了那个。在这种情况下,这可能是更好的选择。但有一点需要注意,“You can use operator Contains”-这不是运算符,而是一个成员方法。 - asawyer

94
myDataTable.Columns.Contains("col_name")

8

如果您需要使用多个列,可以使用类似下面给出的代码。我刚刚查看了这个问题并找到了在Datatable中检查多个列的答案。

 private bool IsAllColumnExist(DataTable tableNameToCheck, List<string> columnsNames)
    {
        bool iscolumnExist = true;
        try
        {
            if (null != tableNameToCheck && tableNameToCheck.Columns != null)
            {
                foreach (string columnName in columnsNames)
                {
                    if (!tableNameToCheck.Columns.Contains(columnName))
                    {
                        iscolumnExist = false;
                        break;
                    }
                }
            }
            else
            {
                iscolumnExist = false;
            }
        }            
        catch (Exception ex)
        {

        }
        return iscolumnExist;
    }

5

使用IndexOf更准确:

If dt.Columns.IndexOf("ColumnName") = -1 Then
    'Column not exist
End If

如果使用Contains,它将无法区分ColumName和ColumnName2。
更新:
If ds.Tables("TableName").Columns.IndexOf("ColumnName") = -1 Then
    'Column not exist
End If

2
包含不具有您所描述的行为。它不像字符串.contains那样。它更像是“我的集合是否包含具有此名称的列?”而不是“我的集合是否包含一个名称包含此名称的列?” - Rémi
我们如何指定表名? 例如,如果ColumnName存在于Table1中... - Flash
是的,我已修改了我的答案。 - supercrash10

1

基于已接受的答案,我创建了一个扩展方法来检查表中是否存在列:

我分享给关心此事的人。

 public static class DatatableHelper
 {
        public static bool ContainColumn(this DataTable table, string columnName)
        {
            DataColumnCollection columns = table.Columns;
            if (columns.Contains(columnName))
            {
                return true;
            }

            return false;
        }
}

并使用 dtTagData.ContainColumn("SystemName")

作为例子。


1
DataColumnCollection col = datatable.Columns;        
if (!columns.Contains("ColumnName1"))
{
   //Column1 Not Exists
}

if (columns.Contains("ColumnName2"))
{
   //Column2 Exists
}

0
值得一提的是,Contains(...)IndexOf(...) >= 0都是不区分大小写的。
一个好的建议是禁止同一名称但仅在大小写上有所不同的多个列存在!但如果你这样做了,那么Contains会显示出一些奇怪的行为:
// In all tests below, "IndexOf(...) >= 0" gives the same result
DataTable dt1 = new DataTable();
dt1.Columns.Add("Test");

dt1.Columns.Contains("Test"); // true, and same result with "IndexOf >= 0"
dt1.Columns.Contains("test"); // true...surprise!
dt1.Columns.Contains("TEST"); // true...surprise again!

DataTable dt2 = new DataTable();
dt2.Columns.Add("Test");
dt2.Columns.Add("test"); // works, but not recommended!
// Note: Adding a 2nd column with the same case, i.e. "Test", is not allowed

dt2.Columns.Contains("test"); // true
dt2.Columns.Contains("Test"); // true
dt2.Columns.Contains("TEST"); // false...huh?

Contains 的性能特点也很奇怪。 dt1.Columns.Contains("Test");dt1.Columns.Contains("test"); 都返回 TRUE。仔细计时显示,当列名与相同大小写存在时,Contains 超级快,几乎像 HashSet::Contains。但是当列名与不同大小写存在时(例如“test”),性能要慢得多,几乎像每个列都被检查了一遍...然后返回值仍为 TRUE!

这些奇怪的行为似乎是 DataTable::Columns::Contains 的一个特点。如果您需要显式区分大小写,或者在列名仅因大小写而不同的情况下获得更一致的行为,请考虑:

private bool ContainsCaseSensitive(DataTable dt, string colName)
{
    foreach (DataColumn col in dt.Columns)
    {
        if (col.ColumnName.Equals(colName))
            return true;
    }
    
    return false;
}

ContainsCaseSensitive 的性能与 Contains 相似,当你搜索的列在 DataTable 中具有较低的 Ordinal 位置或不存在时。对于具有较高 Ordinal 位置的列,则 ContainsCaseSensitiveContainsIndexOf >= 0 稍慢一些。


0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接