在我们的数据库中,我们有一个表格,我们已经映射到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]
有谁知道这是否可行,如果可能的话;怎么写呢?如果不可能,有没有人对如何解决这个问题有任何其他的想法,而不用整个文本实体检索所有的列?
答案 0 :(得分: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");