LINQ版的SQL查询具有多个左联接,分组依据和日期时间转换

时间:2020-07-30 17:49:32

标签: c# sql-server linq

我有以下SQL查询,该查询恰好按预期返回一行数据:

select count(c.ID) as NoteCount, count(s.ClaimStatusHistoryID) as ActionCount, p.DayGoal
from Collector_Profile p
left join ClaimStatusHistory s on s.AppUserID = p.AppUserID and CONVERT(varchar(10), s.StatusDateTZ, 101) = convert(varchar(10), GETDATE(), 101)
left join Claim_Notes c on c.CollectorID = p.ID and CONVERT(varchar(10),c.PostDateTZ,101) = convert(varchar(10), GETDATE(), 101)
where p.ID = 1338
group by p.DayGoal

我正在尝试转换为LINQ。当我尝试包含DbFunctions.TruncateTime时,出现错误,未定义TruncateTime。因此,在此示例中,我已将其注释掉,但我也需要使其正常工作。这是我到目前为止的内容,可以编译但会引发错误:

var utcNow = DateTimeOffset.UtcNow.Date;
var query = from p in _context.Collector_Profile
  join s in _context.ClaimStatusHistory on p.AppUserID 
    equals s.AppUserID into gs 
    // && DbFunctions.TruncateTime(s.StatusDateTZ) equals utcNow into gs
join c in _context.Claim_Notes on p.ID 
    equals c.CollectorID into gc 
    //&& DbFunctions.TruncateTime(c.PostDateTZ) equals utcNow into gc
from s in gs.DefaultIfEmpty()
from c in gc.DefaultIfEmpty()
where p.ID == CollectorID
group new { gs, gc } by p.DayGoal into grouped
select new UserStatistics { DayGoal = grouped.Key, 
   NoteCount = grouped.Count(x => x.gc.Any()), 
   ActionCount = grouped.Count(x => x.gs.Any()) };

return query.FirstOrDefault();
 

运行它时出现以下错误:

InvalidOperationException: Processing of the LINQ expression 'DbSet<Collector_Profile>
 .GroupJoin(
 outer: DbSet<ClaimStatusHistory>, 
 inner: p => p.AppUserID, 
 outerKeySelector: s => s.AppUserID, 
 innerKeySelector: (p, gs) => new { 
 p = p, 
 gs = gs
 })' by 'NavigationExpandingExpressionVisitor' failed. This may indicate either a bug or a limitation in EF Core. See https://go.microsoft.com/fwlink/?linkid=2101433 for more detailed information.

有人可以帮助我使此linq查询正常工作吗?感谢您的协助和示例。我已经看了很多问题,但是没有一个人在做我发现的事情。

1 个答案:

答案 0 :(得分:1)

我认为这应该可行,除非出现DateTimeOffset.Date和时区问题。

由于EF Core 3仅对转换GroupJoin(基本上仅转换为LEFT JOIN)提供了非常有限的支持,因此您必须将查询分为两部分,一个是使用LEFT JOIN的SQL查询,然后客户端GroupBy来创建GroupJoin的效果。

var utcNowDate = DateTimeOffset.UtcNow.Date;

var dbQuery = from p in _context.Collector_Profile
              where p.ID == CollectorID
              join s in _context.ClaimStatusHistory.Where(s => s.StatusDateTZ.Value.Date == utcNowDate) on p.AppUserID equals s.AppUserID into gs
              from s in gs.DefaultIfEmpty()
              join c in _context.Claim_Notes.Where(c => c.PostDateTZ.Value.Date == utcNowDate) on p.ID equals c.CollectorID into gc
              from c in gc.DefaultIfEmpty()
              select new { p.DayGoal, s = s.ClaimStatusHistoryID, c = c.ID };

var query = from psc in dbQuery.AsEnumerable()
            group new { psc.s, psc.c } by psc.DayGoal into grouped
            select new UserStatistics {
                DayGoal = grouped.Key,
                NoteCount = grouped.Count(sc => sc.c != null),
                ActionCount = grouped.Count(sc => sc.s != null)
            };

return query.FirstOrDefault();