简体   繁体   中英

DefaultIfEmpty in LINQ-to-SQL join causing duplicates

Here is an extract of my query:

...
join p in dc.PODs on c.ID equals p.Consignment into pg
from pgg in pg.DefaultIfEmpty()
...

What the query should do is get all the 'PODs' associated with a consignment, store it as an IEnumerable object (which seems to work) so I can run through it when querying the main IEnumerable generated from the query.

The problem is, I am getting duplicate main rows with the DefaultIfEmpty line, which only happens when a row has multiple PODs - so it's returning a row for each POD, which is incorrect. If I take out the pg.DefaultIfEmpty() line, it seems to work a bit better, but I still want to get the rows without PODs.

Any ideas guys?

Just want to confirm for your 2nd case, wouldn't the output be without the Two, Four, Five which have none item since it is not an outer join? One 1 TextBox Three 3 Refridgerator 3 Bucket

What I tried was use an equivalent WHERE IN for dc.PODS. ....join appraisal in ef_appraisal on application.a_appraisalid equals appraisal.a_appraisalid
where
(from r in..
select r.r_applicationid).Contains(application.a_id) )

Do share if you have other ideas

Forgive me if I'm off on your intention because I can't see the complete structure of your data or your initial from or final select clause in your query excerpt. So I'm posting what I think is a solution based on your snippet and sample data I constructed. Let me know if I'm off and I'll correct it.

If you want a list of rows of consignments to PODs, with each consignment to POD on its own line, you could do something like this (keep in mind my from and select clause are based on my sample data):

        // select the consignment id & name (i made up) and each matching POD
        var results = from c in consignments
                      join p in dc.PODs on c.ID equals p.Consignment into pg
                      from pgg in pg.DefaultIfEmpty()
                      select new { ID = c.ID, Name = c.Name, POD = pgg };

        // This is just a SAMPLE display just for kicks and grins
        foreach (var r in results)
        {
            Console.WriteLine(r.Name + " " + ((r.POD != null)
                                                ? (r.POD.Consignment + " " + r.POD.Description)
                                                : "none"));
        }

This query outputs something like:

One 1 TextBox
Two none
Three 3 Refridgerator
Three 3 Bucket
Four none
Five none

However I'm not quite sure I understand your remark:

"The problem is, I am getting duplicate main rows"

I'm not sure if you're saying you don't want to see the one consignment per purchase per row where each result in the IEnumerable is an item with the consignment and a sequence of PODs, you'd want a query like:

        // select the Consignment ID and Name (i made up), and list of PODs
        // instead of the individual POD
        var results = from c in consignments
                      join p in dc.PODs on c.ID equals p.Consignment into pg
                      select new { ID = c.ID, Name = c.Name, PODs = pg };

        // This is just a SAMPLE display just for kicks and grins
        foreach (var r in results)
        {
            Console.WriteLine(r.Name + " ");

            if (r.PODs.Count() > 0)
            {
                foreach (var pod in r.PODs)
                {
                    Console.WriteLine("\t" + pod.Consignment + " " + pod.Description);
                }
            }
            else
            {
                Console.WriteLine("\tNone");
            }
        }

Where the select is selecting the POD list instead of the individual match, which outputs like this:

  One
        1 TextBox
  Two
        None
  Three
        3 Refridgerator
        3 Bucket
  Four
        None
  Five
        None

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