简体   繁体   中英

EF core 2.1 select/distinct

I'm using sql profiler to see sql generated by Ef core2.1, this is my linq query :

var resulat = (from a in A
               join b in B equals a.level=b.level
               where ...
               select new M1 {AId = a.id}).Distinct();

(from r in resulat
 join c in C equals r.AId = c.AId
 select new M2 
 {
   CId = c.Id,
   level = _helper(c.level)
 }).Distinct();

Sql generated:

select t.AId,c.Id,c.level
from 
 (
    select distinct a.id 
    from A a
    inner join B b on a.level=b.level   
    where ...       
 ) as t
inner join C c on t.AId = c.AId

What i want as result is :

select distinct c.Id,c.level
from 
(
    select distinct a.id 
    from A a
    inner join B b on a.level=b.level   
    where ...       
) as t
inner join C c on t.AId = c.AId

I have tried also using select/distinct with result IQueryable, but the sql generated is the same. what i missed in my linq query or what i have to add to have this sql query

That's what worked for me:

  1. Delete Distinct() from result query, this avoid adding t.AId to my selection.
  2. Delete a helper method from one of my selection fields performe adding Distinct() to final query.

This is my query after correction:

    var resulat = from a in A
                  join b in B equals a.level=b.level
                  where ...
                  select new M1 {AId = a.id};

    (from r in resulat
    join c in C equals r.AId = c.AId
    select new M2 
    {
      CId = c.Id
      level = c.level
    }).Distinct();

Many thanks for your comments, it really helped me.

I'm always a fan of querying the data you want directly from the table (well, DbSet) that returns the data. The process looks a bit like these steps:

  1. I want C.Id and C.Level
  2. That's context.Cs .
  3. Which C s do I want?
  4. The ones that have a parent A , of which at least one B has the same 'level' as A and meets a couple of other criteria (the where ... ).

That amounts to:

from c in context.Cs
where context.Bs.Any(b => b.level == c.A.level && <other criteria>)
select new { c.Id, c.Level }

If the where ... also contains filter criteria for A you can add predicates like && cA == ... to the where .

Note that I assume a navigation property cA to be present, otherwise to be created, because C has AId .

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