2015-10-12 43 views
0

我使用datareader從sqltable中使用sqlcommand檢索一些值。現在,當我第一次執行閱讀器來選擇值並將它們分配給RemovedRows變量時,它完美地工作。但是當它下次執行時會填充AddedRows變量,它什麼也不返回。現在,如果我交換可變位置,AddedRows將具有值,而後者將不會有任何內容。因此,基本上讀者執行一次,下一次將不執行,也doen't給出任何錯誤,如讀取器已關閉等使用IDataReader正確讀取值

using (IDataReader reader = _changeTable.ExecuteReader()) 
{ 
    RemovedRows = reader.Select(r => new { LogID = r["LogID"], Operation = r["SYS_CHANGE_OPERATION"] }) 
         .Where(r => r.Operation.Equals("D")).Select(r => (long)r.LogID).ToList(); 

    AddedRows = reader.Select(r => new { LogID = r["LogID"], Operation = r["SYS_CHANGE_OPERATION"] }) 
        .Where(r => r.Operation.Equals("I")).Select(r => (long)r.LogID).ToList(); 
} 

public static IEnumerable<T> Select<T>(this IDataReader reader, 
              Func<IDataReader, T> projection) 
{ 
    while (reader.Read()) 
    { 
     yield return projection(reader); 
    } 
} 

一種解決方案是具有new List<T>讀者的價值觀和訪問新名單值而不用擔心讀者狀態。我能夠創建一個列表,但由於屬性是匿名類型,我無法訪問它。

我創建new List<T>和使用它像這樣:

public static List<T> CreateList<T>(params T[] elements) 
    { 
     return new List<T>(elements); 
    } 


var values = reader.Select(r => new { LogID = r["LogID"], Operation = r["SYS_CHANGE_OPERATION"] }).ToList(); 
var newList = Helper.CreateList(values); 

RemovedRows = newList.Where(r => r.Operation.Equals("D")).Select(r => (long)r.LogID).ToList(); 

這不允許我訪問匿名類型的操作和性能LOGID。

所以我的問題是我怎麼能執行讀寫器(下面的代碼),後來關閉讀者使用後其值:

var values = reader.Select(r => new { LogID = r["LogID"], Operation = r["SYS_CHANGE_OPERATION"] }).ToList(); 

回答

2

讀者已經列舉,並只允許一次性正向只有訪問,所以試圖枚舉它得到AddedRows結果在一個空的集合。我建議你閱讀完所有相關的行到內存中,然後過濾成單獨的查詢:

string[] ops = {"D","I"}; 

IEnumerable<long> removedRows; 
IEnumerable<long> addedRows; 

using (IDataReader reader = _changeTable.ExecuteReader()) 
{ 
    var allRows = reader.Select(r => new { LogID = r["LogID"], Operation = r["SYS_CHANGE_OPERATION"] }) 
         .Where(r => ops.Contains(r.Operation) 
         .ToList(); 

    removedRows = allRows.Where(r => r.Operation.Equals("D")) 
         .Select(r => (long)r.LogID); 

    addedRows = allRows.Where(r => r.Operation.Equals("I")) 
         .Select(r => (long)r.LogID); 
} 

你也可以使用GroupByToLookup得到了類似的結果,但使用任何最有意義給你,除非你有重大的性能問題。

+0

是的,它的工作原理。我之前嘗試過,但我不確定它爲什麼不起作用。非常感謝您的回覆。 – Marshal