【发布时间】:2022-01-05 21:25:10
【问题描述】:
我有一个包含对象列表的 SQL 表,我正在尝试使用许多不同的条件返回一个列表。
这是我的对象(与 SQL 表相同):
class Photo{
public int Id { get; set; }
public string FileName { get; set; }
public DateTime Uploaded { get; set; }
public int? ProjectId { get; set; }
public int GalleryOrder { get; set; }
}
在 SQL 表中,随着时间的推移上传了许多照片,这些照片可能会或可能不会用ProjectIds 标记。每个ProjectId 都有许多照片标签。分批上传,这样可能会有很多张同一个DateTime Uploaded的照片,然后用GalleryOrder整理。
鉴于ProjectIds 的列表,我试图根据以下参数为每个项目返回一张代表照片:
- 每个 ProjectId 一张照片
- 最近上传日期
- 最低画廊顺序
我有一些代码似乎可以与我的测试数据库(大约 20 个条目)一起使用,但它会提取过多的数据并且有多种类型。我不确定如何简化和优化它。
这是我当前的查询:
public async Task<List<Photo>> GetOneImageFilesPerProject(List<int> projectIds)
{
using var context = _contextFactory.CreateDbContext();
var results = await context.Photos.Where(x => x.ProjectId != null
&& projectIds.Contains((int)x.ProjectId))
.ToListAsync();
results = results.OrderBy(x => x.ProjectId)
.ThenByDescending(x => x.Uploaded)
.ThenBy(x => x.GalleryOrder)
.GroupBy(x => x.ProjectId)
.Select(x => x.First())
.ToList();
return results;
}
该程序使用在.Where 调用之后添加的OrderBy、GroupBy 和Select 调用进行编译,但它似乎在此时挂起并且永远不会返回最终列表。这就是为什么它分为两个处理步骤。
我的另一个想法是从 Db 中获取列表,然后通过 foreach 循环构建最终列表。不确定这是否比使用.GroupBy 和.Select 更快。无论哪种方式似乎有点不雅和蛮力。如果有一个直接的 SQL 查询会是一个更好的解决方案,我愿意接受!
是否有更直接的方法可以根据对象列表中的其他条件返回具有一个唯一项的列表?
就规模而言,这不会是一个庞大的应用程序,但它会一次查找约 10-20 个项目 ID,每个项目可能有约 40-50 个标记的照片。许多案例会小一点(2-5 张照片),但有些更大(100-200 张照片)。用户会非常频繁地运行此功能,例如一天几次,并且照片列表会频繁变化。
编辑:使用 .NET 5 和 EF Core 5
【问题讨论】:
-
哪个 EF Core 版本?
-
EF core 5, .NET 5。如果它有很大的不同,我可以更新到 .NET 6,但它不在近期计划中。
-
是的,EF Core 6 应该翻译这个查询。您只需从第一个查询中删除
ToListAsync并将其保留为IQueryable。它应该更快,但不是非常理想。
标签: c# entity-framework linq entity-framework-core