我建议使用过滤器模式,您可以在其中针对 IEnumerable 编写扩展方法。这样一来,您的大部分逻辑就被封装到您可以反复使用的方法中:
public static class TextExtensions
{
[System.Runtime.CompilerServices.Extension]
public static IEnumerable<Text> ByTextId(this IEnumerable<Text> qry, int textId)
{
return qry.Where(t => t.TextId == textId);
}
[System.Runtime.CompilerServices.Extension]
public static IEnumerable<Text> ByLanguage(this IEnumerable<Text> qry, string language)
{
return qry.Where(t => t.Language == language);
}
}
然后你的代码变成:
var texts = MyDB.Texts.ByTextId(1).ByLanguage("Danish");
然后重复就不再是问题了。我还建议让自己成为一个静态类来保存各种语言值以避免硬编码:
public static class LanguageValues
{
public static string English
{
get
{
return "English";
}
}
public static string Danish
{
get
{
return "Danish";
}
}
}
然后你的代码变成:
var texts = MyDB.Texts.ByTextId(1).ByLanguage(LanguageValues.Danish);
您可以将其与 DefaultIfEmpty 方法结合使用,该方法为您提供:
var texts = MyDB.Texts.DefaultIfEmpty(MyDB.Texts.ByTextId(1).ByLanguage(LanguageValues.English).Single()).ByTextId(1).ByLanguage(LanguageValues.Danish);
然后将其放入一个单独的扩展方法中以供重复使用:
[System.Runtime.CompilerServices.Extension]
public static IEnumerable<Text> GetValueOrDefault(this IEnumerable<Text> qry, int textId, string language)
{
return qry.DefaultIfEmpty(qry.ByTextId(textId).ByLanguage(LanguageValues.English).Single()).ByTextId(textId).ByLanguage(language);
}
您现在可以简单地调用:
var text = MyDB.Texts.GetValueOrDefault(1, LanguageValues.Danish);
请注意,这可以用作任何查询的最后一步,所以这样的事情也可以工作:
var text = MyDB.Texts.Where(<some funky clause>).Where(<some other funky clause>).GetValueOrDefault(1,LanguageValues.Danish);
正如人们所指出的那样,如果您使用多种备份语言,则有比在原始问题中一次检查一种语言更好的方法,但是这种过滤器模式可以很好地工作,只需定义正确的过滤您的用例和策略。