我在很多Entity Framework查询中都使用一种通用模式,我想找到一种减少重复的方法。 (我使用的是EF内核,但我想这可能也适用于其他版本。)
基本上,我有一个Resource
对象和一个Translation
对象。对于给定的资源,我需要获得翻译,最好是在当前的语言环境中进行翻译(如果可以的话),并避免出现一些后备(可能是英语)的情况,如果不存在,则请提供翻译。
模式本质上是这样的:
MyContext.Foos
.Where(f => f.Id > -1)
.Select(f => new {
FooId = f.Id,
Translation = f.Resource.Translations
.OrderBy(t => t.Culture == "fr" ? 1 : t.Culture == "en" ? 2 : 3)
.Select(t => t.Value)
.FirstOrDefault()
})
.ToList();
这将导致以下单个SQL查询:
SELECT [f].[Id], (
SELECT TOP(1) [b].[Value]
FROM [Translations] AS [b]
WHERE [f.Resource].[Id] = [b].[ResourceId]
ORDER BY CASE
WHEN [b].[Culture] = N'en'
THEN 1 ELSE CASE
WHEN [b].[Culture] = N'fr'
THEN 2 ELSE 3
END
END
) AS [x]
FROM [Foos] AS [f]
INNER JOIN [Resources] AS [f.Resource] ON [f].[ResourceId] = [f.Resource].[Id]
许多不同的对象都在利用资源,我希望能够通过做这样的事情来整理一下(并使它更干燥):
MyContext.Foos
// .Include(f => f.Resource.Translations)
.Where(f => f.Id > -1)
.Select(f => new {
FooId = f.Id,
Translation = f.Resource.GetTranslation("fr", "en")
})
.ToList();
public static string GetTranslation(this Resource resource, string primary, string secondary)
{
return resource.Translations
.OrderBy(t => t.Culture == "fr" ? 1 : t.Culture == "en" ? 2 : 3)
.Select(t => t.Value)
.FirstOrDefault()
}
这实际上为翻译返回空值。我尝试添加.Includes(...)
无济于事。我也尝试过这种替代方法,它是在翻译的集合而不是资源对象上调用的:
public static string GetTranslation(this IEnumerable<Translation> translations, string primary, string secondary)
{
return translations
.OrderBy(b => b.Culture == primary ? 1 : b.Culture == secondary ? 2 : 3)
.Select(b => b.Value)
.FirstOrDefault();
}
这完全返回了我想要的内容,但是它运行了两个查询!第一个只是选择资源主键:
SELECT [f.Resource].[Id]
FROM [Foos] AS [f]
INNER JOIN [Resources] AS [f.Resource] ON [f].[ResourceId] = [f.Resource].[Id]
WHERE [f].[Id] > -1
ORDER BY [f].[Id], [f.Resource].[Id]
第二个执行了我需要的操作,但实际上再次运行了第一个查询:
SELECT [f.Resource.Translations].[Id], [f.Resource.Translations].[Culture], [f.Resource.Translations].[ResourceId], [f.Resource.Translations].[Value], [t].[Id], [t].[Id0]
FROM [Translations] AS [f.Resource.Translations]
INNER JOIN (
SELECT [f0].[Id], [f.Resource0].[Id] AS [Id0]
FROM [Foos] AS [f0]
INNER JOIN [Resources] AS [f.Resource0] ON [f0].[ResourceId] = [f.Resource0].[Id]
WHERE [f0].[Id] > -1
) AS [t] ON [f.Resource.Translations].[ResourceId] = [t].[Id0]
ORDER BY [t].[Id], [t].[Id0]
是否有某种方式编写一种扩展方法,该方法基本上可以用作通常使用的Linq语句序列(可以转换为单个SQL查询)的简写?