IDataReader和“HasColumn”,最佳方法?

时间:2009-01-09 21:13:37

标签: c# ado.net idatareader

我已经看到了两种检查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 个答案:

答案 0 :(得分: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 :(得分:1)

很大程度上取决于你如何使用HasColumn。你只是召唤一次或两次,还是反复循环?该列是否可能存在或者提前完全未知?

设置行过滤器可能每次都会进行表扫描。 (另外,从理论上讲,GetSchemaTable()可以在每次调用时生成一个全新的表,这会更加昂贵 - 我不相信SqlDataReader会这样做,但是在IDataReader级别,谁知道呢?)但是如果你只是称之为一次或两次我无法想象这是一个很大的问题(除非你有数千列或其他东西)。

(但是,我会至少将GetSchemaTable()的结果存储在方法中的本地var中,以避免在快速连续中调用它两次,如果没有将其缓存在特定IDataReader重新生成它的某个地方。)

如果您事先知道在正常情况下您要求的列将存在,则异常方法更加可口(因为实际上,不存在列的情况是例外情况)。即使不是,它可能表现稍好一些,但除非你反复调用它,否则你应该问问自己性能是否真的非常重要。

如果你反复调用它,你可能应该考虑一种不同的方法,例如:预先调用GetSchemaTable(),循环遍历表,并将字段名称加载到Dictionary或其他一些结构中。专为快速查找而设计。

答案 2 :(得分:0)

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

过早优化只会引导您走向不必要的复杂实施。实现最适合您的版本,然后衡量性能影响。如果与您的性能要求相比是不可接受的,那么请考虑替代方案。