2015-10-21 82 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