1

在我们的数据库中,我们有一个如下所示的表,我们已将其映射到 Database-First EF 模型中的实体:

CREATE TABLE Texts(
  Id integer,
  Eng nvarchar(max),
  Nob nvarchar(max),
  ...
)

该表中的一行可能非常大,因此我们只想获取用户所做的语言选择当前需要的列的值。

我的想法是有一个扩展功能来为我做这件事,但我不知道也找不到任何方法来编写它(如果可能的话)。我尝试了一些变体,但(显然)它失败了,但有一个例外,指出它不能被翻译成商店表达式。所以我有点卡住了。

这个函数的使用思路是:

context.Codes.Where(row => row.Id == 234).Select(row => new {
  row.Id,
  Text = Text.GetLocalizedText("Eng") // This should generate an SQL that only retrieves the Eng 
                                      // column of the Text navigation property (which is 
                                      // connected to the Texts table.
});

这应该会生成一个与此类似的选择(与上面的示例类似,但直接使用 Text.Eng 除外):

SELECT 
[Extent1].[Id] AS [Id], 
[Extent2].[Eng] AS [Eng]
FROM  [dbo].[Codes] AS [Extent1]
INNER JOIN [dbo].[Texts] AS [Extent2] ON [Extent1].[TextId] = [Extent2].[Id]
WHERE 234 = [Extent1].[Id]

有谁知道这是否可行,是否可行;怎么写?如果不可能,是否有人对如何在不检索包含所有列的整个 Text 实体的情况下解决此问题有任何其他想法?

4

1 回答 1

0

的扩展方法IQueryable<Code>可以工作,但它不像您可能想要的那样灵活,因为您需要为每种要执行的投影类型提供扩展,并且您不能使用匿名结果对象。

这个想法基本上是这样的:

您需要一个可以投影到的命名类(而不是匿名类):

public class CodeData
{
    public int Id { get; set; }
    public string LocalizedText { get; set; }
}

然后是带有语言参数的扩展方法:

public static class CustomExtensions
{
    public static IQueryable<CodeData> SelectCodeData(
        this IQueryable<Code> query, string language)
    {
        switch (language)
        {
            case "Eng":
                return query.Select(code => new CodeData
                {
                    Id = code.Id,
                    LocalizedText = code.Text.Eng
                });

            case "Nob":
                return query.Select(code => new CodeData
                {
                    Id = code.Id,
                    LocalizedText = code.Text.Nob
                });
            //... more languages
        }

        throw new ArgumentException("Invalid language code.", "language");
    }
}

然后可以这样调用:

using CustomExtensions;

// ...

IQueryable<CodeData> codeDataQuery = context.Codes
    .Where(row => row.Id == 234)
    .SelectCodeData("Eng");
于 2013-03-30T15:26:52.407 回答