不是一个严重的问题,但仍然非常不愉快...好的,所以环境是: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。是的,可以单独返回两个字段,然后决定哪个字段将在客户端,但是当查询用作数据源时,此方法将停止工作。