我有一个人员表和其他相关表 - 订单、联系人历史记录、地址和电子邮件。 Persons 表包含基本详细信息 - 姓名、出生日期和一些其他属性。 表的类包含 Persons 表引用的表的集合,因此,我可以在需要的过滤器或引用的查询中使用它们。
所有这些表都具有在每次更新时设置的
Updated
属性。
我需要返回一页按最新更改降序排列的结果。
因此,如果有人更改某人的地址、更改姓名或联系该人,所有这些操作都应将该人移至顶部。
我的查询的基本部分看起来像
var result = await _context
.Persons
.Include(p => p.Addresses)
.Include(p => p.Emails)
.Include(p => p.Orders)
.Include(p => p.ContactHistory)
.OrderByDescending(p => p.Updated)
.AsSplitQuery()
.AsNoTracking()
.ToArrayAsync();
我需要更改
OrderByDescending(p => p.Updated)
以包含其他表格。
我不能使用
ThenBy
,因为这不起作用 - 只有当所有先前的日期都相同时,接下来的每个部分才会对数据进行排序。
我需要类似
OrderByDescending(p => Max(p.Updated, p.Addresses.Updated, p.Emails.Updated ... and so on))
的东西
如果找不到解决方案,我正在考虑编写一个 SQL Server 函数并使用 EF Core 从 C# 代码调用它。
我将如何在 T-SQL 中执行此操作的示例:
select distinct top 10 p.* from persons p
inner join Addresses a on p.id = a.PersonId
inner join Emails e on p.id = e.PersonId
inner join Orders o on p.id = o.PersonId
inner join ContactHistory c on p.id = c.PersonId
order by (select max(updated) from (values(p.Updated), (a.Updated),
(e.Updated), (o.Updated), (c.Updated)) t(updated))
不幸的是,这不是最有效的查询,但业务需求需要这种逻辑。
我也愿意接受有关如何解决这个问题的其他建议 - 也许存在我不知道的模式或其他东西。
我很确定这个任务不是唯一的,这个问题已经在这里被问过很多次了,但我找不到关键字来发现它,所以,我真诚地为可能的重复而提前道歉。
尝试以下查询。它为每个人准备最后更新的信息。然后加入您的原始查询并做出适当的顺序。
// append filters
var personsQuery = _context.Persons;
var orderQuery =
from p in personsQuery
from e in p.Emails
from o in p.Orders
from h in p.ContactHistory
group new { p, e, o, h } by p.Id into g
select new
{
PersonId = g.Key,
LastUpdated = g.Max(x => Math.Max(x.p.Updated, Math.Max(x.e.Updated, Math.Max(x.o.Updated, x.h.Updated))))
}
orderQuery = orderQuery
.OrderByDescending(p => p.LastUpdate)
.Take(10);
var query = personsQuery
.Include(p => p.Addresses)
.Include(p => p.Emails)
.Include(p => p.Orders)
.Include(p => p.ContactHistory);
query =
from q in query
join o in orderQuery on q.Id equals o.PersonId
orderby o.LastUpdated descending
select q;
var result = await query
.AsSplitQuery()
.AsNoTracking()
.ToArrayAsync();