如何有效的在 LINQ 查询中处理异常?
                                                            生活随笔
收集整理的這篇文章主要介紹了
                                如何有效的在 LINQ 查询中处理异常?
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.                        
                                咨詢區
- Jader Dias 
參考下面的代碼:
myEnumerable.Select(a?=>?ThisMethodMayThrowExceptions(a));如何保證在 Linq 的查詢過程中即使拋出了異常,查詢不會被提前中斷,就好像在每層迭代上都有默認的 try catch 塊。
回答區
- LeBaptiste 
我寫了一個小的擴展方法,它可以實現在 IEnumerable<T> 中的每一層迭代上加上 try catch 異常處理邏輯, 擴展方法代碼如下:
public?static?class?OnCaughtExceptionExtension {public?static?IEnumerable<SelectTryResult<TSource,?TResult>>?SelectTry<TSource,?TResult>(this?IEnumerable<TSource>?enumerable,?Func<TSource,?TResult>?selector){foreach?(TSource?element?in?enumerable){SelectTryResult<TSource,?TResult>?returnedValue;try{returnedValue?=?new?SelectTryResult<TSource,?TResult>(element,?selector(element),?null);}catch?(Exception?ex){returnedValue?=?new?SelectTryResult<TSource,?TResult>(element,?default(TResult),?ex);}yield?return?returnedValue;}}public?static?IEnumerable<TResult>?OnCaughtException<TSource,?TResult>(this?IEnumerable<SelectTryResult<TSource,?TResult>>?enumerable,?Func<Exception,?TResult>?exceptionHandler){return?enumerable.Select(x?=>?x.CaughtException?==?null???x.Result?:?exceptionHandler(x.CaughtException));}public?static?IEnumerable<TResult>?OnCaughtException<TSource,?TResult>(this?IEnumerable<SelectTryResult<TSource,?TResult>>?enumerable,?Func<TSource,?Exception,?TResult>?exceptionHandler){return?enumerable.Select(x?=>?x.CaughtException?==?null???x.Result?:?exceptionHandler(x.Source,?x.CaughtException));}public?class?SelectTryResult<TSource,TResult>{internal?SelectTryResult(TSource?source,?TResult?result,?Exception?exception){Source?=?source;Result?=?result;CaughtException?=?exception;}public?TSource?Source?{?get;?private?set;?}public?TResult?Result?{?get;?private?set;?}public?Exception?CaughtException?{?get;?private?set;?}} }接下來就可以像下面這樣使用了。
public?void?Test() {List<string>?completedProcesses?=?initialEnumerable.SelectTry(x?=>?RiskyOperation(x)).OnCaughtException(exception?=>?{?_logger.Error(exception);?return?null;?}).Where(x?=>?x?!=?null)?//?filter?the?ones?which?failed.ToList(); }當然你有興趣的話,還可以實現一個 SkipOnException 擴展方法,當在迭代中出現異常時自由選擇是否可以跳過異常處理。
- THTP 
如果你 select 的是 IQueryable 類型,這時候你可能需要在 Expression 上擴展而不是 Lambda,參考如下擴展方法。
public?static?class?ExpressionHelper {public?static?Expression<Func<TSource,?TResult>>?TryDefaultExpression<TSource,?TResult>(Expression<Func<TSource,?TResult>>?success,?TResult?defaultValue){var?body?=?Expression.TryCatch(success.Body,?Expression.Catch(Expression.Parameter(typeof(Exception)),?Expression.Constant(defaultValue,?typeof?(TResult))));var?lambda?=?Expression.Lambda<Func<TSource,?TResult>>(body,?success.Parameters);return?lambda;} }然后像下面這樣使用。
[Test] public?void?Test() {var?strings?=?new?object?[]?{"1",?"2",?"woot",?"3",?Guid.NewGuid()}.AsQueryable();var?ints?=?strings.Select(ExpressionHelper.TryDefaultExpression<object,?int>(x?=>?Convert.ToInt32(x),?0));Assert.IsTrue(ints.SequenceEqual(new[]?{1,?2,?0,?3,?0})); }點評區
其實面對這種場景,我第一個想到的還是 Polly 框架,大家有興趣可以看一看:https://github.com/App-vNext/Polly
總結
以上是生活随笔為你收集整理的如何有效的在 LINQ 查询中处理异常?的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: 【自定义控件】c#winform自定义控
- 下一篇: 宇宙最強的IDE - Visual St
