加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > asp.Net > 正文

asp.net – 高效地加入Entity Framework Core中另一个表的最新记

发布时间:2020-12-16 06:40:30 所属栏目:asp.Net 来源:网络整理
导读:我从 PHP w / MySQL转到ASP .NET Core. 问题: 为了说明,假设以下两个表: T:{ID,描述,FK}和状态:{ID,ID_T,时间,状态}.它们之间存在1:n关系(ID_T引用T.ID). 我需要来自T的所有记录,其中包含一些特定的FK值(比如1)以及各州的相关最新记录(如果有的话). 在S
我从 PHP w / MySQL转到ASP .NET Core.

问题:

为了说明,假设以下两个表:
T:{ID,描述,FK}和状态:{ID,ID_T,时间,状态}.它们之间存在1:n关系(ID_T引用T.ID).

我需要来自T的所有记录,其中包含一些特定的FK值(比如1)以及各州的相关最新记录(如果有的话).

在SQL方面,它可以写成:

SELECT T.ID,T.Description,COALESCE(s.State,0) AS 'State' FROM T
LEFT JOIN (
    SELECT ID_T,MAX(Time) AS 'Time'
    FROM States
    GROUP BY ID_T
) AS sub ON T.ID = sub.ID_T
LEFT JOIN States AS s ON T.ID = s.ID_T AND sub.Time = s.Time
WHERE FK = 1

我正在努力在LINQ(或流畅的API)中编写有效的等效查询.到目前为止,我得到的最佳解决方案是:

from t in _context.T
where t.FK == 1
join s in _context.States on t.ID equals o.ID_T into _s
from s in _s.DefaultIfEmpty()
let x = new
{
    id = t.ID,time = s == null ? null : (DateTime?)s.Time,state = s == null ? false : s.State
}
group x by x.id into x
select x.OrderByDescending(g => g.time).First();

当我在输出窗口中检查生成的SQL查询时,它就像:

SELECT [t].[ID],[t].[Description],[t].[FK],[s].[ID],[s].[ID_T],[s].[Time],[s].[State]
FROM [T] AS [t]
LEFT JOIN [States] AS [s] ON [T].[ID] = [s].[ID_T]
WHERE [t].[FK] = 1
ORDER BY [t].[ID]

它不仅选择了比我需要的更多的列(在真实的方案中,它们有更多的列).查询中没有分组,因此我认为它从数据库中选择所有内容(并且状态将变得很大)并且分组/过滤在数据库外部发生.

问题:

你会怎么做?

> LINQ / Fluent API中是否存在有效查询?
>如果没有,可以使用哪些变通方法?

>原始SQL破坏了从特定数据库技术中抽象的概念,它在当前的实体框架核心中使用非常笨重(但也许是最好的解决方案).
>对我来说,这看起来是使用数据库视图的一个很好的例子 – 再次,Entity Framework Core并不真正支持(但也许是最好的解决方案).

解决方法

如果您尝试对LINQ进行更直接的翻译会发生什么?

var latestState = from s in _context.States
                  group s by s.ID_T into sg
                  select new { ID_T = sg.Key,Time = sg.Time.Max() };

var ans = from t in _context.T
          where t.FK == 1
          join sub in latestState on t.ID equals sub.ID_T into subj
          from sub in subj.DefaultIfEmpty()
          join s in _context.States on new { t.ID,sub.Time } equals new { s.ID,s.Time } into sj
          from s in sj.DefaultIfEmpty()
          select new { t.ID,t.Description,State = (s == null ? 0 : s.State) };

显然是??运算符将转换为COALESCE并可以正确处理空表,因此您可以将select替换为:

select new { t.ID,State = s.State ?? 0 };

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读