我有以下数据模型:
AuthorizationObject [1 : n] Scopes
我想执行以下选择:
var result = await _context.AuthorizationObject
.Select(x => new
{
x.RoleId,
x.DefinitionId,
Scopes = x.Scopes.Select(s => s.Name).ToList()
})
.ToListAsync();
由于我必须关注性能,我想在一个选择中执行它,如(伪):
select a.RoleId a.DefinitionId s.Name from AuthorizationObject As a
inner join Scope As s ...
不幸的是它执行了类似的事情:
SELECT [x].[RoleId], [x].[DefinitionId], [x].[Id]
FROM [AuthorizationObject] AS [x]
SELECT [s].[ScopeDefinitionId]
FROM [Scope] AS [s]
WHERE @_outer_Id = [s].[AuthorizationObjectId]
SELECT [s].[ScopeDefinitionId]
FROM [Scope] AS [s]
WHERE @_outer_Id = [s].[AuthorizationObjectId]
SELECT [s].[ScopeDefinitionId]
FROM [Scope] AS [s]
WHERE @_outer_Id = [s].[AuthorizationObjectId]
SELECT [s].[ScopeDefinitionId]
FROM [Scope] AS [s]
WHERE @_outer_Id = [s].[AuthorizationObjectId]
SELECT [s].[ScopeDefinitionId]
FROM [Scope] AS [s]
WHERE @_outer_Id = [s].[AuthorizationObjectId]
...
更新 @ SamiAl90建议的解决方案: 此查询
var result = await _context.AuthorizationObject
.Include(x => x.Scopes)
.ToListAsync();
生成以下sql:
SELECT [x].[Id], [x].[DefinitionId], [x].[Metadata], [x].[RoleId]
FROM [AuthorizationObject] AS [x]
ORDER BY [x].[Id]
SELECT [x.Scopes].[AuthorizationObjectId], [x.Scopes].[ScopeDefinitionId], [x.Scopes].[ValueString]
FROM [Scope] AS [x.Scopes]
INNER JOIN (
SELECT [x0].[Id]
FROM [AuthorizationObject] AS [x0]
) AS [t] ON [x.Scopes].[AuthorizationObjectId] = [t].[Id]
ORDER BY [t].[Id]
答案 0 :(得分:0)
使用includes。
var result = await context.Set<AuthorizationObject>()
.AsQueryable()
.Include(a => a.Scopes)
.ToListAsync();
这将使用INNER JOIN创建一个查询,但作为子选择。但仍有一个问题。
现在,如果你真的需要一个伪对象,你仍然可以创建一个伪对象,但它不应该是IMO。
修改:添加了sample project,证明这不会导致两次查询。
这就是创建的查询
SELECT [p.Children].[Id], [p.Children].[ParentId]
FROM [ChildClass] AS [p.Children]
INNER JOIN (
SELECT [p0].[Id]
FROM [ParentClass] AS [p0]
) AS [t] ON [p.Children].[ParentId] = [t].[Id]
ORDER BY [t].[Id]