2015-10-21 114 views
0

我目前使用此代码来检查是否有DataReader的现有列:优化循环结果?

public static class DataRecordExtensions 
{ 
    public static bool HasColumn(this IDataRecord dr, string columnName) 
    { 
     for (int i=0; i < dr.FieldCount; i++) 
     { 
      if (dr.GetName(i).Equals(columnName, StringComparison.InvariantCultureIgnoreCase)) 
       return true; 
     } 
     return false; 
    } 
} 

我重用这个代码很多,所以它不断通过运行For循环。

反正我有可以优化呢?例如,如果列不存在,那么它表示结果对于所有内容都是相同的,我不必再遍历所有内容。同样如果它是现有的,我知道它是存在的,并且不需要再次通过循环。

谢谢!

+0

您是否为每条记录调用此方法?使用这种方法的代码片段会很有帮助。 –

+3

如何填写'HashSet existingColumnNames' * *然后只检查'existingColumnNames.Contains(columnName)'? – Corak

+0

感谢Ufuk和Corak。我喜欢Corak的建议,我会尽力去做,看看表现如何。 – Water

回答

3

该函数的代码很好。例如,您应该检查您的调用代码,以便在您的DataReader或DataTable的每次迭代中都不要调用此代码。

你应该调用此方法一次遍历所有的记录之前。机会很渺茫,表格或光标的每一行都不会有相同的列。

+0

好点,但确实取决于有多少“客户”正在调用此代码,他们如何调用以及多久。 – Matt

+0

谢谢nvoigt。正如马特所说,我们有几个数据库表和每个表的独立DataReader。对于该表的每一行,我们填充一组项目。这部分是我们调用HasColumn的地方,因为如果数据库中没有该属性的列,则无法填充Item属性。 – Water

3

的主要问题是在调用代码...但你能避免调用方法不止一次总体上更通过改变你的方法来创建并返回一个HashSet<string>

public static class DataRecordExtensions 
{ 
    public static ISet<string> GetFieldNames(this IDataRecord dr, StringComparer comparer) 
    { 
     var sequence = Enumerable.Range(0, dr.FieldCount) 
           .Select(i => dr.GetName(i)); 
     return new HashSet<string>(sequence, comparer); 
    } 
} 

你然后可以用您的第一条记录调用该方法,并将StringComparer.InvariantCultureIgnoreCase作为比较器传递,然后您将返回ISet<string>,您可以便宜地测试它是否包含特定字段名称。

的尴尬部分可能调用此一次。你可能会需要这样的东西:

ISet<string> fields = null; 
while (reader.Read()) 
{ 
    var record = ...; 
    if (fields == null) 
    { 
     fields = record.GetFieldNames(StringComparer.InvariantCultureIgnoreCase); 
    } 
    // Use fields and record here 
} 

您也可能要考虑返回Dictionary<string, int>代替ISet<string>的,如果你需要的领域为好。

+0

谢谢乔恩!非常有帮助,我认为这是我想要实现的。 – Water

0

一个选择是列名保存在一个字典,你可以使用这个非常快速地查找列名。

由于您使用的是扩展方法,你需要使用ConditionalWeakTable来存储和检索你的字典对于给定的数据读取器。检查它是否存在,如果不存在,使用这种方法存储它。

请记住你第一次调用这个它可能会比它慢,现在是因为你不能短路的方法(如您需要获得所有的列名缓存)。如果这是一个问题,您可以使用混合方法进行缓存,直到找到您之后退出的列,然后下一次如果您未在缓存中找到该列,请继续搜索并将其添加到缓存中新列,当您找到您之后的列时(或者您到达列的末尾),就会再次退出。

我应该说,这三种方式是最好的(你的电流加上这两个)在很大程度上取决于:

  1. 你多少次调用此方法对于给定的数据读取器
  2. 多少列你在你的数据读取器,以及
  3. 您搜索的列及顺序

例如,如果你在你的读者100列,并寻找在POSI列97然后98然后99,我上面的第一种方法可能是最好的(首先使用缓存)。但是,如果您在位置1和位置100搜索列,然后混合方法之间的几个可能会更好。用你目前的方法在任何地方搜索一次数据读取器就会更好!

+0

谢谢马特!会考虑这个! – Water