EF6 GroupJoin()重复一次子查询

时间:2015-05-05 11:43:41

标签: sql-server vb.net entity-framework

不是一个严重的问题,但仍然非常不愉快...好的,所以环境是:SQL Server 2012,VS 2012,.NET 4.5 WinForms,EF 6.1.3

我正在尝试从表中检索数据,以及它在当前语言上的本地化(由用户选择)。如果我自己编写查询,它将如下所示:

declare @Id int = 1, @CultureCode varchar(50) = 'en';

select ci.Id, ci.Name, ci.ItemPosition,
    isnull(vls.TextData, ci.Description) as [Description]
from dbo.SomeTable ci
    left join dbo.ViewLocalisedStrings vls on vls.CultureCode = @CultureCode
        and vls.ObjectType = 'SOMETYPE' and vls.RowId = ci.Id
where ci.ClassifierId = @Id;

在这里,我只有在缺少本地化时才会使用项目描述。在应用程序中,已编译以下构造(Ctx是实体框架上下文引用):

Ctx.SomeTable.Where(Function(c) c.ClassifierId = ClId).GroupJoin( _
    Ctx.ViewLocalisedStrings.Where(Function(c) c.CultureCode = G_DBCulture And c.ObjectType = "SOMETYPE"), _
    Function(o) o.Id,
    Function(vls) vls.RowId,
    Function(o, vls) New With { _
        .Id = o.Id, _
        .Name = o.Name, _
        .ItemPosition = o.ItemPosition, _
        .Description = CStr(If(vls.FirstOrDefault().TextData, o.Description))
    } _
)

然而,由EF生成的查询结果远非完美:

declare @p__linq__0 int = 1, @p__linq__1 nvarchar(4000) = 'en';

SELECT 
    [Project6].[Id] AS [Id], 
    [Project6].[Name] AS [Name], 
    [Project6].[ItemPosition] AS [ItemPosition], 
    CASE WHEN ([Project6].[C1] IS NULL) THEN [Project6].[Description] ELSE [Project6].[C2] END AS [C1]
    FROM ( SELECT 
        [Project4].[Id] AS [Id], 
        [Project4].[ItemPosition] AS [ItemPosition], 
        [Project4].[Name] AS [Name], 
        [Project4].[Description] AS [Description], 
        [Project4].[C1] AS [C1], 
        (SELECT TOP (1) 
            [Extent3].[TextData] AS [TextData]
            FROM [dbo].[ViewLocalisedStrings] AS [Extent3]
            WHERE ([Extent3].[CultureCode] = @p__linq__1) AND ('SOMETYPE' = [Extent3].[ObjectType]) AND ([Project4].[Id] = [Extent3].[RowId])) AS [C2]
        FROM ( SELECT 
            [Project3].[Id] AS [Id], 
            [Project3].[ItemPosition] AS [ItemPosition], 
            [Project3].[Name] AS [Name], 
            [Project3].[Description] AS [Description], 
            [Project3].[C1] AS [C1]
            FROM ( SELECT 
                [Project1].[Id] AS [Id], 
                [Project1].[ItemPosition] AS [ItemPosition], 
                [Project1].[Name] AS [Name], 
                [Project1].[Description] AS [Description], 
                (SELECT TOP (1) 
                    [Extent2].[TextData] AS [TextData]
                    FROM [dbo].[ViewLocalisedStrings] AS [Extent2]
                    WHERE ([Extent2].[CultureCode] = @p__linq__1) AND ('SOMETYPE' = [Extent2].[ObjectType]) AND ([Project1].[Id] = [Extent2].[RowId])) AS [C1]
                FROM ( SELECT 
                    @p__linq__1 AS [p__linq__1], 
                    [Extent1].[Id] AS [Id], 
                    [Extent1].[ItemPosition] AS [ItemPosition], 
                    [Extent1].[Name] AS [Name], 
                    [Extent1].[Description] AS [Description]
                    FROM [dbo].[SomeTable] AS [Extent1]
                    WHERE [Extent1].[ClassifierId] = @p__linq__0
                )  AS [Project1]
            )  AS [Project3]
        )  AS [Project4]
    )  AS [Project6];

本地化文本被检索两次(或更多 - 取决于使用的是哪个函数而不是If()),然后每个版本以我想要查看的方式在最终的CASE语句中使用,真的。

有没有人知道如何通过生成更好的查询来实现这一目标?如果不重新设计数据库(可能),欢迎提出任何建议。

P.S。是的,可以单独返回两个字段,然后决定哪个字段将在客户端,但是当查询用作数据源时,此方法将停止工作。

0 个答案:

没有答案