简体   繁体   中英

LINQ version of sql query with multiple left joins, group by, and datetime conversion

I have the following SQL query which is returning one row of data exactly as expected:

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

I am trying to convert to LINQ. When I attempt to include the DbFunctions.TruncateTime, I get an error that TruncateTime is not defined. So I have commented them out in this example, but I need to get that working as well. This is what I have so far, which compiles but throws an error:

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();
 

I get the following error when I run it:

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.

Can someone help me to get this linq query working? Thanks for any assistance and examples. I've looked at lots of questions and none are doing exactly what I'm doing that I've found yet.

I believe this should work, barring issues with DateTimeOffset.Date and timezones.

Since EF Core 3 only has extremely limited support for translating GroupJoin (basically just to LEFT JOIN ), you must split the query into two parts, a SQL query with LEFT JOIN and then a client side GroupBy to create the effect of 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();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM