【发布时间】:2021-06-06 15:26:59
【问题描述】:
我准备了一个示例数据模型来说明我的问题,所以不要看模型的含义。
public class Job
{
public int Id { get; set; }
public ICollection<Task> Tasks { get; set; }
}
public class Task
{
public int Id { get; set; }
public Job Job { get; set; }
public ICollection<Record> Records { get; set; }
}
public class Record
{
public int Id { get; set; }
public int RecordID { get; set; }
public Task Task { get; set; }
public int? Priority { get; set; }
//More fields, which are be different for every RecordID
}
Input:JobId
Output: 分配给tasks 的所有records 分配给具有给定ID 的Job。容易吧?但是,对我来说问题很复杂,因为结果输出集合只能包含具有唯一 RecordId 的记录。如果同一个RecordId有重复,则必须选择优先级值最高的Record(如果优先级值为null,则其值最低,如果null记录较多,则顺序可能随机) .
我非常关心应用服务器的性能和 RAM,因此我希望在数据库端(SQL Server)上执行查询,而不是在应用代码中出现奇怪的循环。就我而言,我要查询的records 甚至会达到几百万。
例子:
Input: JobId = 5
Tasks Table:
| Id | JobId |
|---|---|
| 1 | 5 |
| 2 | 5 |
| 3 | 5 |
Records Table:
| Id | TaskId | RecordId | Priority | more fields... | |
|---|---|---|---|---|---|
| 1 | 1 | 101 | null | AAA | |
| 2 | 2 | 101 | null | BBB | |
| 3 | 1 | 102 | 9 | CCC | |
| 4 | 2 | 102 | 10 | DDD | |
| 5 | 2 | 105 | 2 | EEE | |
| 6 | 3 | 106 | 3 | FFF |
结果:
| Id | TaskId | RecordId (unique in results) | Priority | more fields... | |
|---|---|---|---|---|---|
| 1 | 1 | 101 | null | AAA | |
| 4 | 2 | 102 | 10 | DDD | |
| 5 | 2 | 105 | 2 | EEE | |
| 6 | 3 | 106 | 3 | FFF |
我开始编写查询,但总是以 C# 中的怪异循环和一个额外的集合来复制结果数据而告终,而在应用程序中,包含一百万条记录的额外集合似乎有点过头了。
var job = await _dbContext.Job.SingleAsync(x=>x.Id = jobId);
return await job.Tasks.SelectMany(s => s.Records). ...//what next?
or
return = await _dbContext.Records.Where(r => r.Task.Job.Id jobId). ...//what next?
【问题讨论】:
-
Linq 是在
RecordId上执行GroupBy,然后在Select上在Priority上执行OrderBy并获取Last。但是,对于 EF Core,取决于版本,它可能不会翻译,或者它会默默地在内存中进行分组。
标签: c# .net sql-server linq entity-framework-core