这是一个我无法回答的问题。我目前有以下简单的代码段。
return _context.UserProfiles
.Single(p => p.ID == userID)
.Organisations
.Select(p => new { ID = p.ID })
.First()
.ID;
这只是获取第一个用户配置文件(拉为SELECT * FROM UserProfiles WHERE ...),这很好。问题是组织导航属性。
我首先使用代码进行迁移,因此在EF自动创建的UesrProfiles和组织(多对多)之间存在联结表。我最终得到了Organizations的userprofile导航属性和Members的组织导航属性。所以,很容易。
组织导航属性的问题在于它没有投射。在select和first上我得到以下SQL发送到数据库服务器。
SELECT
[Extent2].[ID] AS [ID],
[Extent2].[Description] AS [Description],
[Extent2].[ShortDescription] AS [ShortDescription],
[Extent2].[Name] AS [Name],
[Extent2].[Address] AS [Address],
[Extent2].[City] AS [City],
[Extent2].[State] AS [State],
[Extent2].[PostCode] AS [PostCode],
[Extent2].[Country] AS [Country],
[Extent2].[Created] AS [Created],
[Extent2].[CreatedBy] AS [CreatedBy]
FROM [dbo].[OrganisationMembers] AS [Extent1]
INNER JOIN [dbo].[Organisations] AS [Extent2] ON [Extent1].[Organisation_ID] = [Extent2].[ID]
WHERE [Extent1].[UserProfile_ID] = @EntityKeyValue1
由于我只投影ID,我应该得到以下内容吗?
SELECT
[Extent2].[ID] AS [ID]
FROM [dbo].[OrganisationMembers] AS [Extent1]
INNER JOIN [dbo].[Organisations] AS [Extent2] ON [Extent1].[Organisation_ID] = [Extent2].[ID]
WHERE [Extent1].[UserProfile_ID] = @EntityKeyValue1
加入是正确的,因为我期望但不是列。我想我可以为联结表创建另一个对象,然后编写代码加入并手动选择,但这是我希望EF能为我做的事情。
更新
我只是没有玩从First()带回的原始用户配置文件的排序和预测。如果我将代码更改为:
return _context.UserProfiles
.Select(p => new { ID = p.ID, Organisations = p.Organisations.Select(q => new { ID = q.ID }) })
.Single(p => p.ID == userID)
.Organisations
.First()
.ID;
我最终得到了这个怪物:
SELECT
[Project1].[ID] AS [ID],
[Project1].[C1] AS [C1],
[Project1].[Organisation_ID] AS [Organisation_ID]
FROM ( SELECT
[Limit1].[ID] AS [ID],
[Extent2].[Organisation_ID] AS [Organisation_ID],
CASE WHEN ([Extent2].[Organisation_ID] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C1]
FROM (SELECT TOP (2) [Extent1].[ID] AS [ID]
FROM [dbo].[UserProfiles] AS [Extent1]
WHERE [Extent1].[ID] = @p__linq__0 ) AS [Limit1]
LEFT OUTER JOIN [dbo].[OrganisationMembers] AS [Extent2] ON [Limit1].[ID] = [Extent2].[UserProfile_ID]
) AS [Project1]
ORDER BY [Project1].[ID] ASC, [Project1].[C1] ASC
但是,我猜它会像我想的那样投射我的ids。
更新2
根据Gongdo的回答,我更新了以下内容:
return _context.UserProfiles
.Where(p => p.ID == userID)
.Take(1)
.SelectMany(p => p.Organisations)
.Select(p => new { ID = p.ID })
.First().ID;
哪个输出:
SELECT
[Limit2].[Organisation_ID] AS [Organisation_ID]
FROM ( SELECT TOP (1)
[Extent2].[Organisation_ID] AS [Organisation_ID]
FROM (SELECT TOP (1) [Extent1].[ID] AS [ID]
FROM [dbo].[UserProfiles] AS [Extent1]
WHERE [Extent1].[ID] = @p__linq__0 ) AS [Limit1]
INNER JOIN [dbo].[OrganisationMembers] AS [Extent2] ON [Limit1].[ID] = [Extent2].[UserProfile_ID]
) AS [Limit2]
我更接近我想要的输出。谢谢你。
答案 0 :(得分:1)
Single
,SingleOrDefault
,First
和FirstOrDefault
本身就是投影方法。所以你需要保持IQueryable,直到你真正需要投影它。跟随会按你的意愿工作。
return _context.UserProfiles
.Where(p => p.ID == userID)
.SelectMany(p => p.Organisations)
.Select(p => new { ID = p.ID })
.First()
.ID;