C# SingleOrDefault:Catch just";序列包含多个元素;无效操作例外
在我们的项目中,我们最近添加了一个旧数据导入工具,在该工具中,我们将这些旧数据转换为应用程序中可用的对象。在本次导入中,我们有以下代码:C# SingleOrDefault:Catch just";序列包含多个元素;无效操作例外,c#,.net,linq,exception-handling,invalidoperationexception,C#,.net,Linq,Exception Handling,Invalidoperationexception,在我们的项目中,我们最近添加了一个旧数据导入工具,在该工具中,我们将这些旧数据转换为应用程序中可用的对象。在本次导入中,我们有以下代码: using (var session = documentStore.OpenSession()) { try { var cluster = session.Query<ClusterState>().SingleOrDefault(x => x.Name == clusterString);
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;
}
}
它可以在本地工作,但不能在服务器上工作。这是因为我们有一台荷兰服务器,所以它没有使用“序列包含多个元素”
,而是使用“Reeks bevat meerdere elementen”
“无效操作异常”。现在我知道我可以将代码修改为:
if (String.Equals(e.Message, "Sequence contains more than one element")
|| String.Equals(e.Message, "Reeks bevat meerdere elementen"))
当然,这是可行的,我不认为我们打算在将来使用不同的语言服务器,但这仍然是非常糟糕的代码,如果消息在新的.NET/LINQ版本中发生更改,这将不再有效
那么,是否有其他方法可以捕获仅包含一个以上元素的序列InvalidOperationException,而不捕获任何其他的InvalidOperationException
我是否应该添加一个
Count
检查或其他检查,以查看是否接收到多个匹配元素而不是Try-Catch,或者是否有一种独特的方法来过滤“序列包含多个元素”
异常?或者我应该捕获所有“InvalidOperationExceptions”并添加一个额外的日志行,以便我们获得这些异常的通知吗?您可以将程序的区域性设置为en,我们可以解决您的问题
例如:
// 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");
}
}
publicstatictsource SingleOnlyOrDefault(此IEnumerable源,
Func谓词)
{
如果(source==null){抛出新的ArgumentNullException(“source”);}
如果(谓词==null){throw new
参数异常(“谓词”);
}
IEnumerable matchingItems=source.Where(谓词);
int matchedItemCount=matchingItems.Count;
开关(matchedItemCount)
{
案例0:返回默认值(TSource);
案例1:返回匹配项[0];//或单个()
默认值:抛出新异常(“条件存在太多元素”);
}
}
Hmm,听起来确实很有希望。荷兰语的例外有点烦人,而且一开始翻译得很糟糕,我们经常使用谷歌来翻译例外,以了解给出了哪个英语错误。如果我们能够使整个应用程序英语化,尽管有一台荷兰服务器,但它将带来比这个问题更多的好处。(我会看看我是否能做到这一点,如果我能做到,我会接受你的回答。如果我不能做到,我可能会询问更多关于如何做到这一点的细节。)我与同事讨论了这一点,还问我们不总是使用英国文化是否有原因。当然有,因为荷兰语格式有不同的日期和时间、不同的小数等。它目前使用机器的默认区域性。即使在我的机器上我的语言是英语,其他的东西,如日期和时间都是荷兰语。(这在我的问题中并不清楚,所以您的解决方案仍然是一个很好的答案,但不幸的是对我们不起作用。)我想我正在删除try-catch,只需执行一次选择
,然后查看是否包含多个
。@KevinCruijssen-您可以尝试创建扩展方法,这可能会对您有所帮助。.检查udpated answer此异常通常不会被视为可恢复的运行时异常。这可能就是为什么他们没有为它创建一个单独的异常类。您不应该处理这个异常错误,获取一个列表并查看计数。
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");
}
}