为实体框架(核心)中的常规查询编写扩展方法?

时间:2018-10-22 10:28:45

标签: entity-framework

我在很多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查询)的简写?

0 个答案:

没有答案