咨询区

  • 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 查询中处理异常?相关推荐

  1. linq 查询中嵌套子查询

    开发工具与关键技术:VS NVC 作者:听民谣的老猫 撰写时间:2019/7/22 18:15 讲一个比较实用的功能____linq 查询中嵌套子查询. 通常我们遇到上面这种情况,我们肯定是想吧后面班 ...

  2. linq查询中嵌套子查询

    为了实现某个模块的功能时,需要查询数据时而这些数据又没有在同一张表里面,为了方便调用数据,就会创建实体类来封装这些数据,由于数据是关联多张表的那么实体类里面就会有多个列表对象,就比如在项目权限管理的权 ...

  3. NET问答:在 Linq 查询中可以处理异常吗?

    咨询区 Jader Dias: 先上例子: myEnumerable.Select(a => ThisMethodMayThrowExceptions(a)); 如何让上面的 Linq查询 即使 ...

  4. [译]如何在C#中调试LINQ查询

    LINQ是我在C#中最喜欢的功能之一.它让代码看起来更漂亮美观.我们得到了一个易于编写和理解的简洁函数式语法.好吧,至少我们可以使用LINQ方法的语法风格. LINQ很难进行调试.我们无法知道该查询内 ...

  5. asp.net linq查询环境搭建

    本文是以sqlserver2008为数据库,vs2013为开发工具来介绍的. 要搭建这样一个数据库的操作环境,首先建立一个类库项目 然后在这个类库项目中添加几个类:DBDataContext数据库上下 ...

  6. 3种重构EF Linq查询的方法而不扼杀性能

    目录 枚举<问题> 返回解决方案[0] 但等等,还有更多 或是LinqKit? 总结 从实体框架LINQ查询中提取方法会悄然扼杀性能.这里有三个简单的解决方案,包括:表达式,扩展方法和Li ...

  7. java中抛出异常快捷键_idea中处理异常的快捷键

    建议68:从System.Exception或其他常见的基本异常中派生异常 微软建议:从System.Exception或其他常见基本异常之一派生异常.在Visual Studio中输入Excepti ...

  8. LINQ 查询简介(MSDN)

    查询是一种从数据源检索数据的表达式.查询通常用专门的查询语言来表示.随着时间的推移,人们已经为各种数据源开发了不同的语言:例如,用于关系数据库的 SQL 和用于 XML 的 XQuery.因此,开发人 ...

  9. 基本 LINQ 查询操作

    获取数据源 在 LINQ 查询中,第一步是指定数据源. 和大多数编程语言相同,在使用 C# 时也必须先声明变量,然后才能使用它. 在 LINQ 查询中,先使用 from 子句引入数据源 (custom ...

最新文章

  1. 嵌入式linux 考试大纲,《嵌入式Linux》课程考试大纲-武汉工程大学学生进
  2. 关于MNIST数据集的处理
  3. Java游戏地下城_地下城与勇士DNF-鬼剑士
  4. Linux学习之创建子进程
  5. jQuery框架学习第九天:jQuery工具函数介绍与使用
  6. 淘宝特价版招聘:年薪50万,35岁以上优先;1900万:一线城市财富自由的入门级门槛;鸿蒙OS成武汉大学专业选修课 | 极客头条...
  7. springMvc配置文件
  8. [导入]一个Form验证的方案
  9. 2021年最新C语言教程入门,C语言自学教程(最全整理)
  10. Unity3D 数学之向量
  11. MacOS 显示隐藏文件快捷键
  12. 一种采集USB热敏小票打印机的硬件,用于商超购物中心营业小票采集的硬件方案
  13. 划片机是芯片切割制造流程中一个重要的环节
  14. 唤客猫获客营销之全员激励
  15. 制作角色血条 [代码清单10-2]
  16. java导出excel文件名乱码_Poi生成excel文件名乱码问题的解决方案
  17. PDF格式分析(一)简介
  18. C语言实现顺序栈的基本操作(初始化、判断空、入栈、出栈、获取栈顶元素)
  19. 服务器看门狗芯片电路图,新型纯硬件看门狗电路设计分析研究
  20. vue的简单使用3-v-for、v-if、v-show等指令的使用

热门文章

  1. JAVA学习日志(7-1-继承)
  2. 在Leangoo里怎么设置看板周期?
  3. 你真的会玩SQL吗?Case也疯狂
  4. Hadoop 2.0 中的资源管理框架 - YARN(Yet Another Resource Negotiator)
  5. extjs 文件加载、解析流程
  6. spring中的BeanFactory与ApplicationContext的作用和区别?
  7. 在Win7中怎样打开摄像头?
  8. ^_^家园游记^_^
  9. 多功能复合机基于用户认证功能的实现过程详解
  10. squid2.6加速WEB支持虚拟主机配置心得体会 .txt