想想存储在这个表中的本地化文本:
表格文本
现在我想为TextId 1选择一个文本.如果"Danish"中没有这个TextId的文本,我想回到"英语".
我可以这样做:
var texts = MyDb.Texts.Where(x=>x.TextId == 1 & x.Language == "Danish");
if (!texts.Any()){
texts = MyDb.Texts.Where(x=>x.TextId == 1 & x.Language == "English");
}
Run Code Online (Sandbox Code Playgroud)
...但是我必须重复Where子句的其余部分,这意味着我正在重复自己(在这个例子中不是那么糟糕,但可能会有更多的条款).
有更简单的方法吗?
我建议使用Filter模式,在其中编写针对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);
}
}
Run Code Online (Sandbox Code Playgroud)
然后你的代码变成:
var texts = MyDB.Texts.ByTextId(1).ByLanguage("Danish");
Run Code Online (Sandbox Code Playgroud)
然后重复变成无问题.我还建议让自己成为一个静态类来保存各种语言值以避免硬编码:
public static class LanguageValues
{
public static string English
{
get
{
return "English";
}
}
public static string Danish
{
get
{
return "Danish";
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后你的代码变成:
var texts = MyDB.Texts.ByTextId(1).ByLanguage(LanguageValues.Danish);
Run Code Online (Sandbox Code Playgroud)
您可以将它与DefaultIfEmpty方法结合使用,该方法为您提供:
var texts = MyDB.Texts.DefaultIfEmpty(MyDB.Texts.ByTextId(1).ByLanguage(LanguageValues.English).Single()).ByTextId(1).ByLanguage(LanguageValues.Danish);
Run Code Online (Sandbox Code Playgroud)
然后通过将其放入单个Extension方法重新使用来完成:
[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);
}
Run Code Online (Sandbox Code Playgroud)
你现在可以简单地打电话:
var text = MyDB.Texts.GetValueOrDefault(1, LanguageValues.Danish);
Run Code Online (Sandbox Code Playgroud)
请注意,这可以用作任何查询的最后一步,所以像这样的东西也可以工作:
var text = MyDB.Texts.Where(<some funky clause>).Where(<some other funky clause>).GetValueOrDefault(1,LanguageValues.Danish);
Run Code Online (Sandbox Code Playgroud)
正如人们所指出的那样,如果你使用多种备份语言,那么有一种方法比在原始问题中一次检查一种语言更好,但是这种过滤模式可以干净利落地工作,只需要为你定义正确的过滤器用例和策略.