SingleOrDefault:仅捕获 "Sequence contains more than one element" InvalidOperationException
SingleOrDefault: Catch just "Sequence contains more than one element" 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"))
它在本地有效,但在服务器上无效。这样做的原因是我们有一个荷兰服务器,所以它提供了 "Reeks bevat meerdere elementen"
InvalidOperationException
而不是 "Sequence contains more than one element"
。现在我知道我可以将代码修改为:
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" 并添加一个额外的日志行以便我们收到这些异常的通知?
您可以将程序的文化设置为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");
}
}
在我们的项目中,我们最近添加了一个旧数据导入工具,我们将这些旧数据转换为我们应用程序中可用的对象。在此导入中,我们有以下代码:
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"))
它在本地有效,但在服务器上无效。这样做的原因是我们有一个荷兰服务器,所以它提供了 "Reeks bevat meerdere elementen"
InvalidOperationException
而不是 "Sequence contains more than one element"
。现在我知道我可以将代码修改为:
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" 并添加一个额外的日志行以便我们收到这些异常的通知?
您可以将程序的文化设置为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");
}
}