Home > Mobile >  EF Core Linq query with grouping: Why does DefaultIfEmpty() not work here?
EF Core Linq query with grouping: Why does DefaultIfEmpty() not work here?

Time:07-26

I have two tables that I'm trying to group with the EF Core equivalent of a Left Join. Table "Orders" lists the total amount of orders placed for a given item in each month of the year:

     ITEM     |     JANUARY     |     FEBRUARY     |     MARCH     |
--------------------------------------------------------------------
     Item A         $5,000            $3,000             $6,000
     Item B         $1,000            $4,000             $5,000
     Item C         $7,000            $9,000             $2,000

Table "Categories" lists the items on offer:

     ITEM     
--------------
     Item A   
     Item B
     Item C
     Item D

I'm trying to join the two lists into a single output table, where all the items from "Categories" are listed along with all the figures given in "Orders", if any. A month column should show "$0" if no orders for the item were placed that month, or zeroes across the board if the item doesn't appear in the Orders table at all:

     ITEM     |     JANUARY     |     FEBRUARY     |     MARCH     |
--------------------------------------------------------------------
     Item A         $5,000            $3,000             $6,000
     Item B         $1,000            $4,000             $5,000
     Item C         $7,000            $9,000             $2,000
     Item D         $0                $0                 $0

My ef core linq query is below, linking Orders to Categories on the Item column. Per the MS documentation linked above, I'm selecting from the grouping using ".DefaultIfEmpty()", since I still want Item D to appear in my list even if it does not appear in the Orders table.

var output = (from c in categories 
                join o in orders on c.item equals o.item into grouping
                from b in grouping.DefaultIfEmpty()
                select new Output_Model
                {
                    product = c.product,
                    January = b.January,
                    February = b.February,
                    March = b.March,
                    April = b.April,
                    May = b.May,
                    June = b.June,
                    July = b.July,
                    August = b.August,
                    September = b.September,
                    October = b.October,
                    November = b.November,
                    December = b.December
                }).ToList();

However, when the query gets to Item D, the process fails with the "Object reference not set" error, and the monthly values throwing a System.NullReferenceException. I thought ".DefaultIfEmpty()" was supposed to handle this sort of thing? The month columns in Output_Model are set as nullable.

If I alter my query so that "Categories" is joined on "Orders" with the same criteria, the process completes successfully, but "Item D" is not included in the list. How can I get this working?

CodePudding user response:

Thanks to @NavoneelTalukdar for this one.

It turned out I need to handle my nullities individually, so after I added null handling to each item in the query, I got the results I was looking for.

var output = (from c in categories 
                join o in orders on c.item equals o.item into grouping
                from b in grouping.DefaultIfEmpty()
                select new 
                {
                    product = c.product,
                    January = b != null ? b.January : 0,
                    February = b != null ? b.February : 0,
                    March = b != null ? b.March : 0,
                    April = b != null ? b.April : 0,
                    May = b != null ? b.May : 0,
                    June = b != null ? b.June : 0,
                    July = b != null ? b.July : 0,
                    August = b != null ? b.August : 0,
                    September = b != null ? b.September : 0,
                    October = b != null ? b.October : 0,
                    November = b != null ? b.November : 0,
                    December = b != null ? b.December : 0
                }).ToList();
  • Related