简体   繁体   中英

Linq query with table joins,case statements, count, group by clauses

I want to run a linq query that will return values to my custom DTO. This particular linq query will need to take into account joins from multiple tables, using switch case statements, count (*) and group by

This is the SQL version sample of the query I will need a LinQ equivalent of...

select 
slm.SLType, 
count(c.EStatID) as EStat, 
COUNT(cpd.TrId) as Training,
COUNT(
CASE WHEN cpd.TrStat=  44 THEN  1 
     WHEN cpd.TrStat!=  44 THEN NULL 
     WHEN cpd.TrStat IS NULL  THEN  NULL 
END) as TrainingComplete,
COUNT(
CASE WHEN cpd.CndAssess =  44 THEN  1 
     WHEN cpd.CndAssess !=  44 THEN NULL 
     WHEN cpd.CndAssess IS NULL  THEN  NULL 
END) as AssessmentComplete
from TabC c , TabCPD cpd, TabSLM slm 
where cpd.SLid = slm.SLid
and c.Id= cpd.CID
and c.O_Id = 1
group by slm.SLType 

It returns records in the following format. I have put each record as a new line with fields separated by commas. The numbers below are just as an example

TypeA, 0 , 1 , 1, 0 
TypeB, 1 , 0 , 1, 0

I am trying to create a linq query in the format like the one below without much luck

var query = 
    from c in TabC, ...... 
    select new MyCustomTableC_DTO
    {
      DTOproperty = c.MatchingTable property,....
    }

MyCustomTableC_DTO will have a property for each field in the query. Any idea how to accomplish this? The query I will use to build a list of type MyCustomTableC_DTO

Thanks for your time...

When you try to convert that SQL statement to LINQ line by line, you would get something like this:

from row in (
    from c in db.TabC
    from cpd in db.TabPD
    from slm in db.TabSLM
    where cpd.SLid == slm.SLid
    where c.Id == cpd.CID
    where c.O_Id == 1
    select new { c, cpd, slm })
group row in row.slm.SLType into g
select new
{
    SLType = g.Key,
    EStat = g.Count(r => r.c.EstatID != null),
    Training = g.Count(r => r.cpd.TrId != null),
    TrainingComplete =
        g.Count(r => r.cpd.TrStat == 44),
    AssessmentComplete =
        g.Count(r => r.cpd.CndAssess == 44)
};

This query however, over complicates things and completely ignores that fact that Entity Framework knows much more about the model and generates all foreign keys as properties on the entities. Besides that, with LINQ, you must often approach things the other way around. In your case for instance, don't start with the TabC or TabSLM entity, but TabPD , since that table is the cross-table. With this knowledge, we can write the LINQ query like this:

from cpd in db.TabCPDs
where cpd.TabC.O_Id == 1
group cpd by cpd.TabSLM.SLType into g
select new
{
    SLType = g.Key,
    EStat = g.Count(r => r.TabC.EstatID != null),
    Training = g.Count(r => r.TrId != null),
    TrainingComplete =
        g.Count(r => r.TrStat == 44),
    AssessmentComplete =
        g.Count(r => r.CndAssess == 44)        
};

This is much simpler and (if I'm not mistaking) has the same result.

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