我目前正在使用此代码检查DataReader是否存在列:
df2
[1] "/Desktop"
[2] "/Desktop/all"
[3] "/Programms"
我重复使用这段代码,因此它会持续运行For循环。
无论如何我可以优化这个吗?例如,如果列不存在,则表示结果对于所有内容都相同,我不必再次遍历所有内容。如果它存在,我知道它是存在的,不需要再次循环。
谢谢!
答案 0 :(得分:3)
该功能的代码很好。您应该检查您的调用代码,例如,不要在DataReader或DataTable的每次迭代中调用它。
在迭代所有记录之前,您应该调用此方法一次。如果表或游标的每一行都没有相同的列,那么机会很小。
答案 1 :(得分: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
}
如果您还需要字段 number ,您可能还需要考虑返回Dictionary<string, int>
而不是ISet<string>
。
答案 2 :(得分:0)
一个选项是将列名存储在字典中,然后可以使用它来快速查找列名。
鉴于您正在使用扩展方法,您需要使用ConditionalWeakTable来存储和检索给定数据读取器的字典。检查它是否存在,如果不是缓存并使用这种方法存储它。
请记住,第一次调用它时,它可能会比现在慢,因为您可以将方法短路(因为您需要将所有列名称缓存)。如果这是一个问题,您可以使用混合方法进行缓存,直到您找到退出后的列,下次如果您在缓存中找不到该列,请继续搜索并添加缓存任何新列,一旦找到您之后的列(或者到达列的末尾),就会立即退出。
我应该说这三种方法中哪一种最好(你目前加上这两种方法)在很大程度上取决于:
例如,如果您的阅读器中有100列并且搜索位置97的列,然后是98然后是99,那么我上面的第一种方法可能是最好的(首次使用时全部缓存)。但是,如果你搜索了位置1和100之后的列,那么混合方法之间的一些可能会更好。只需在任何地方搜索数据阅读器,您最好采用当前的方法!