2013-07-25 94 views
2

實際上它不一定是IDataReader收益回報完成後關閉IDataReader

我有一個功能是這樣的:

public IEnumerable<MyClass> GetObjects() 
{ 
    IDataReader dr = GetSomeDataReader(); 
    while (dr.Read()) 
    { 
    yield return new MyClass(dr); 
    } 
    CloseDBConnections(); 
} 

這是工作的罰款,直到我重構它像這樣:

public IEnumerable<MyClass> GetObjects() 
{ 
    IDataReader dr = GetSomeDataReader(); 
    try 
    { 
    return ProcessReader(dr); 
    } finally { 
    CloseDBConnections(); 
    } 
} 
public IEnumerable<MyClass> ProcessReader(IDataReader dr) 
{ 
    while (dr.Read()) 
    { 
    yield return new MyClass(dr); 
    } 
} 

因爲當CloseDBConnections()執行枚舉這不起作用尚未處理。

GetObjects返回時調用.ToList()是實際執行枚舉的內容,但此時連接已被破壞,並且IDataReader失敗。

在我的實例CloseDBConnections不能從新ProcessReader函數中調用,因爲IDataReader可能來自其他來源(再保在這種情況下,整點)

是否有一個合理的辦法解決這個或者我將不得不復制枚舉代碼?

我試圖把調用ProcessReaderyield return,而不是return但這並不工作,因爲C#(可以理解)認爲我想添加一個IEnumerableIEnumerable

回答

3

如何通過回調調用ProcessReaderCloseDBConnections

public IEnumerable<MyClass> GetObjects() 
{ 
    return ProcessReader(GetSomeDataReader(), CloseDBConnections); 
} 

public IEnumerable<MyClass> ProcessReader(IDataReader dr, Action OnFinished) 
{ 
    try 
    { 
    while (dr.Read()) 
     yield return new MyClass(dr); 
    } 
    finally 
    { 
    if (OnFinished != null) 
     OnFinished(); 
    } 
} 
+0

你應該在'finally'中執行回調。否則,如果迭代提前完成(例如'GetObjects()。First()'),它將不會被執行。 – svick

+0

@svick好點。 – sloth

+0

@DominicKexel我喜歡它。 這就是我最終在Javascript中做了很多事情 – DJL

3

不漂亮,但這應該工作。

public IEnumerable<MyClass> GetObjects() 
{ 
    IDataReader dr = GetSomeDataReader(); 
    try 
    { 
    foreach (var result in ProcessReader(dr)) 
    { 
     yield return result; 
    } 
    } finally { 
    CloseDBConnections(); 
    } 
} 
+0

是的,我確實考慮過這一點。 我希望有一個更清潔的解決方案(如一些神奇的關鍵字或其他)。 在這種情況下,如果上述解決方案是唯一可能的解決方案,那麼似乎不值得費心去重新考慮因素。 我想我可能希望太多了! – DJL