客户有零个或一个语言关联。我想做以下
db.Customer.Select(x => new {
x.Id, x.Name,
Language = new { x.Language?.Id, x.Language?.Name }
})
但是这甚至无法编译,因为linq表达式似乎不知道如何处理null safe get运算符(?.
)。我该怎么做相同的?我希望生成的查询为LEFT OUTER JOIN
Language
,Language
密钥为null,或者对象为null。
答案 0 :(得分:3)
只需使用
db.Customer.Select(x => new {
x.Id, x.Name,
Language = new { (int?)x.Language.Id, x.Language.Name }
})
应该像这样生成SQL(当然表名和列名可能不同)
SELECT
[Extent1].[Id] AS [Id],
[Extent1].[Name] AS [Name],
[Extent1].[Language_Id] AS [Language_Id],
[Extent2].[Name] AS [Name1]
FROM [dbo].[Customers] AS [Extent1]
LEFT OUTER JOIN [dbo].[Languages] AS [Extent2] ON [Extent1].[Language_Id] = [Extent2].[Id]
这是类似问题的另一个example,请看一下生成的SQL。
更新但是,我们需要在投影值类型属性时包含T?
强制转换,否则无法实现查询(ToList()
失败, InvalidOperationException :“附加信息:转换为值类型'System.Int32'失败,因为具体化值为null。结果类型的泛型参数或查询必须使用可空类型。”
Update2:另一种选择是使用此构造
db.Customer.Select(x => new {
x.Id, x.Name,
Language = x.Language != null ? new { x.Language.Id, x.Language.Name } : null
})
SQL看起来像这样
SELECT
[Extent1].[Id] AS [Id],
[Extent1].[Name] AS [Name],
CASE WHEN ([Extent2].[ID] IS NOT NULL) THEN 1 END AS [C1],
[Extent1].[Language_Id] AS [Language_Id],
[Extent2].[Name] AS [Name1]
FROM [dbo].[Customers] AS [Extent1]
LEFT OUTER JOIN [dbo].[Languages] AS [Extent2] ON [Extent1].[Language_Id] = [Extent2].[Id]
并且在具体化时,将生成 null Language
成员(与先前的方法相比,该方法生成所有成员都设置为 null 的实例)