IDataReader和“HasColumn”,最佳方法是什么?

6

我见过两种在IDataReader中检查列是否存在的常见方法:

public bool HasColumn(IDataReader reader, string columnName)
{
  try
  {
      reader.getOrdinal(columnName)
      return true;
  }
  catch 
  {
       return false;
  }
}

或者:

public bool HasColumn(IDataReader reader, string columnName)
{

    reader.GetSchemaTable()
         .DefaultView.RowFilter = "ColumnName='" + columnName + "'";

    return (reader.GetSchemaTable().DefaultView.Count > 0);
}

个人而言,我使用第二种方法,因为我讨厌因为这个原因使用异常。

然而,在大型数据集上,我认为RowFilter可能需要对每列进行表扫描,这可能会非常慢。

有什么想法?

3个回答

5

我认为对于这个老问题,我有一个合理的答案。

我会选择第一种方法,因为它更简单。如果你想避免异常,你可以缓存字段名并在缓存中使用TryGet方法。

public Dictionary<string,int> CacheFields(IDataReader reader)
{

    var cache = new Dictionary<string,int>();
    for (int i = 0; i < reader.FieldCount; i++)
    {
        cache[reader.GetName(i)] = i;
    }
    return cache;
}

这种方法的好处是它更简单,而且可以更好地控制。另外,注意,您可能需要考虑不区分大小写或假名的比较方式,这会使事情变得有些棘手。


1
很多事情取决于您如何使用HasColumn。您是只调用一次或两次,还是在循环中重复调用?该列可能存在还是完全未知?
设置行过滤器可能会每次进行表扫描。(此外,在理论上,GetSchemaTable()可能会在每次调用时生成一个全新的表,这将更加昂贵——我不相信SqlDataReader会这样做,但在IDataReader级别上,谁知道呢?)但是,如果您只调用一次或两次,我无法想象这会成为多大问题(除非您有数千个列之类的东西)。
(但是,至少在方法内部将GetSchemaTable()的结果存储在本地变量中,以避免快速连续调用它两次,如果不缓存它在某个地方,以防万一您特定的IDataReader确实重新生成它。)
如果您预先知道在正常情况下您要请求的列将存在,则异常方法会更容易接受(因为该列不存在实际上是一个异常情况)。即使没有,它的性能也可能稍微好一些,但是再次,除非您反复调用它,否则您应该问自己性能是否真的是那么重要。

如果你正在重复调用它,那么你可能应该考虑另一种方法,比如:在前面调用GetSchemaTable()一次,循环遍历表格,并将字段名称加载到字典或其他设计用于快速查找的结构中。


0

我不会担心性能影响。即使您有一个包含1000列的表(这将是一个巨大的表),您仍然只需要扫描1000行的“表扫描”。这很可能微不足道。

过早地进行优化只会导致您朝着不必要的复杂实现方向前进。实现您认为最好的版本,然后测量其性能影响。如果与您的性能要求相比无法接受,则考虑其他选择。


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