How to check if a column exists in a datatable

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

在最好的情况下,绘制地图总是可能的。但这是不现实的... 因此,在我尝试映射可数据表列值之前,我需要检查该列是否存在。如果我不做这个检查,就会有一个 ArgumentException 异常。

当然,我可以用下面这样的代码来检查:

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

但是现在我有3列要映射,有些或者全部可能已经存在/缺失

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

274628 次浏览

你可以用 operator Contains,

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

DataColumnCollection

可以查看给定 DataTableColumns属性,它是表中所有列的列表。

private void PrintValues(DataTable table)
{
foreach(DataRow row in table.Rows)
{
foreach(DataColumn column in table.Columns)
{
Console.WriteLine(row[column]);
}
}
}

Http://msdn.microsoft.com/en-us/library/system.data.datatable.columns.aspx

myDataTable.Columns.Contains("col_name")

对于多列,你可以使用类似于下面给出的代码。我正在浏览这篇文章,找到了在 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;
}
DataColumnCollection col = datatable.Columns;
if (!columns.Contains("ColumnName1"))
{
//Column1 Not Exists
}


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

It is much more accurate to use IndexOf:

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

如果使用“包含”,则不会区分 ColumName 和 ColumnName2。

更新:

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

基于已接受的答案,我提出了一种扩展方法来检查表中的列是否存在

I shared for whom concern.

 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;
}
}

And use as dtTagData.ContainColumn("SystemName")

值得指出的是,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;
}

当要搜索的列在 DataTable 中的 Ordinal位置较低或不存在时,ContainsCaseSensitive的性能类似于 Contains。对于 Ordinal位置较高的列,则 ContainsCaseSensitive略慢于 ContainsIndexOf >= 0