我有一个有许多孩子的复杂对象,我试图只从中选择一些属性及其子项以在网格中显示。之前通过盲目地抛出所需的每个.Include()
来构建查询的方式生成了一个1095行的SQL语句。
从子对象获取单个属性没有问题,但是这个属性是执行的最后一个活动的名称。对集合执行.Last().Name
会抛出一个异常,即它无法转换为SQL。我将提供一个基本示例来帮助可视化(所有FK实际上都在我的代码中设置,这不是问题):
public class Foo
{
public int Id { get; set; }
// just a dummy class everyone knows for illustration
public Address Address { get; set; }
public ICollection<Activity> Activities { get; set; }
}
public class Activity
{
public string Name { get; set; }
}
public class FooModel
{
public int Id { get; set; }
public string StreetName { get; set; }
public string LastActivity { get; set; }
}
这是我设置的查询的基本示例:
public IEnumerable<FooModel> GetHomePageItems(IEnumerable<int> fooIds)
{
return await context.Foos
.Where(f => fooIds.Contains(f.id))
.Select(f => new FooModel
{
Id = f.Id,
StreetName = f.Address.Street,
// here is the problem as it can't
// convert this to SQL
LastActivity = f.Activities.Last().Name
})
.ToListAsync();
}
这件事是否可以完成,或者我是否必须在没有LastActivity
的情况下完成任务,然后使用GroupBy查询活动并以这种方式获取它们?
答案 0 :(得分:3)
您可以尝试将查询更改为:
var query = context.Foos
.Where(f => fooIds.Contains(f.Id))
.Select(f => new FooModel
{
Id = f.Id,
StreetName = f.Address.Street,
LastActivity = f.Activities.OrderByDescending(x => x.Id).FirstOrDefault().Name
}).ToListAsync();
linq为Entity Framework V6.1.3生成以下sql:
SELECT
[Filter1].[Id1] AS [Id],
[Filter1].[Street] AS [Street],
[Limit1].[Name] AS [Name]
FROM (SELECT [Extent1].[Id] AS [Id1], [Extent2].[Street] AS [Street]
FROM [dbo].[Foos] AS [Extent1]
LEFT OUTER JOIN [dbo].[Addresses] AS [Extent2] ON [Extent1].[Address_Id] = [Extent2].[Id]
WHERE [Extent1].[Id] IN (1, 2, 3, 4) ) AS [Filter1]
OUTER APPLY (SELECT TOP (1) [Project1].[Name] AS [Name]
FROM ( SELECT
[Extent3].[Id] AS [Id],
[Extent3].[Name] AS [Name]
FROM [dbo].[Activities] AS [Extent3]
WHERE [Filter1].[Id1] = [Extent3].[Foo_Id]
) AS [Project1]
ORDER BY [Project1].[Id] DESC ) AS [Limit1]
这对您的项目来说可能已经足够了。但是,在大量数据上,您可能需要更快地切换到某些内容,甚至可能使用.Sql()
方法进行手动查询。
实体框架无法识别.LastOrDefault()
和.Last()
方法,而应使用.FirstOrDefault()
或.First()
方法与OrderBy()
或OrderByDescending()
相结合