SingleOrDefault:仅捕获“序列包含多个元素”InvalidOperationException

时间:2015-06-29 06:55:41

标签: c# .net linq exception-handling invalidoperationexception

在我们的项目中,我们最近为旧数据添加了一个导入工具,我们将这些旧数据转换为应用程序中的可用对象。在此导入中,我们有以下代码:

using (var session = documentStore.OpenSession())
{
    try
    {
        var cluster = session.Query<ClusterState>().SingleOrDefault(x => x.Name == clusterString);
        return cluster != null
            ? (ClusterId) cluster.AggregateId
            : null;
    }
    catch (InvalidOperationException e)
    {
        if (String.Equals(e.Message, "Sequence contains more than one element"))
        {
            Logger.Warn("More than one cluster found with the given string: {0}", clusterString);
            if (...)
            {
                return ...
            }
            return null;
        }

        throw;
    }
}

我的问题如下:

if (String.Equals(e.Message, "Sequence contains more than one element"))

它适用于本地,但不适用于服务器。这样做的原因是我们有一个荷兰服务器,因此它不是"Sequence contains more than one element"而是"Reeks bevat meerdere elementen" InvalidOperationException。现在我知道我可以修改代码:

if (String.Equals(e.Message, "Sequence contains more than one element")
    || String.Equals(e.Message, "Reeks bevat meerdere elementen"))

当然这很有效,而且我认为我们打算将来不再使用不同的语言服务器,但是,它仍然是非常糟糕的代码,如果消息随着新的.NET / LINQ版本而改变,那么不再工作了。

那么,除了"Sequence contains more than one element" InvalidOperationException之外,还有其他方法可以捕获InvalidOperationExceptions吗?

我应该添加Count支票或其他内容,以查看我是否收到多个匹配元素而不是Try-Catch,还是只有一种区分"Sequence contains more than one element"例外?或者我应该只捕获所有“InvalidOperationExceptions”并添加一个额外的日志行,以便我们收到这些例外的通知?

1 个答案:

答案 0 :(得分:2)

您可以将程序文化设置为en-US可以解决您的问题

示例:

 // Change current culture
  CultureInfo culture;
  if (Thread.CurrentThread.CurrentCulture.Name == "fr-FR")
     culture = CultureInfo.CreateSpecificCulture("en-US");
  else
     culture = CultureInfo.CreateSpecificCulture("fr-FR");

  Thread.CurrentThread.CurrentCulture = culture;
  Thread.CurrentThread.CurrentUICulture = culture;

创建您的扩展方法并将您自己的异常作为备用解决方案

public static TSource SingleOnlyOrDefault<TSource>(this IEnumerable<TSource> source,
        Func<TSource, bool> predicate)
    {
        if (source == null) { throw new ArgumentNullException("source"); }
        if (predicate == null) { throw new   
                         ArgumentNullException("predicate");    
    }

    IEnumerable<TSource> matchingItems = source.Where(predicate);
    int matchedItemCount = matchingItems.Count;

        switch (matchedItemCount)
        {
            case 0: return default(TSource);
            case 1: return matchingItems[0]; // Or Single() 
            default: throw new Exception("Too many element exist for    condition");
        }
    }