Linq Join Iquery, How to Use Defaultifempty

Linq join iquery, how to use defaultifempty

You basically want to do a left outer join. The way you currently are using the DefaultIfEmpty method is that if the entire list is empty you provide a single default entry.

You should join with PassengerDetails and for each passenger details list call the default if empty. This is the equivalent of a left outer join and it goes a little something like this:

var data = from fd in FlightDetails
join pd in PassengersDetails on fd.Flightno equals pd.FlightNo into joinedT
from pd in joinedT.DefaultIfEmpty()
select new {
nr = fd.Flightno,
name = fd.FlightName,
passengerId = pd == null ? String.Empty : pd.PassengerId,
passengerType = pd == null ? String.Empty : pd.PassengerType
}

Understanding DefaultIfEmpty in LINQ

I ain't generally answer my own question, however, I think some people might find the question somewhat intricate.
In the first step, the working logic of the DefaultIfEmpty method group should be figured out(LINQ doesn't support its overloaded versions, by the by).

class foo
{
public string Test { get; set; }
}
// list1
var l1 = new List<foo>();
//l1.Add(null); --> try the code too by uncommenting
//list2
var l2 = l1.DefaultIfEmpty();

foreach (var x in l1)
Console.WriteLine((x == null ? "null" : "not null") + " entered l1");

foreach (var x in l2)
Console.WriteLine((x == null ? "null" : "not null") + " entered l2");

When being run, seeing that it gives null entered l2 out result out.
What if l1.Add(null); is commented in? It is at your disposal, not hard to guess at all.

l2 has an item which is of null since foo is not one of the building block types like Int32, String, or Char. If it were, default promotion would be applied to, e.g. for string, " "(blank character) is supplied to.

Now let's examine the LINQ statement being mentioned.

Just for a remembrance, unless an aggregate operator or a To{a
collection}() is applied to a LINQ expression, lazy evaluation(honor
deferred) is carried out.

Sample Image

The followed image, albeit not belonging to C#, helps to get what it means.

In the light of the lazy evaluation, we are now wisely cognizant of the fact that the LINQ using query expression is evaluated when requested, that is, on-demand.

Sample Image

So, ps contains product items iff the equality expressed at on keyword of join is satisfied. Further, ps has different product items at each demand of the LINQ expression. Otherwise, unless DefaultIfEmpty() is used, select is not hit thereby not iterating over and not yielding any Console.WriteLine($"{productName}: {category}");. (Please correct me at this point if I'm wrong.)

Errors using DefaultIfEmpty() in LINQ query with group by

Try the following query:

var query = 
from r in DbContext.Railcars
from p in DbContext.ProductAliases
.Where(pa => pa.Product.Company.CompanyCode == companyCode && pa.Alias == r.Product)
.Select(pa => pa.Product.Name)
.Take(1)
.DefaultIfEmpty()
where r.Facility.Company.CompanyCode == companyCode && r.Departure == null
group r by p ?? r.Product into productGroup
select new
{
Product = productGroup.Key,
Count = productGroup.Count()
};

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

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

Linq Left Join Fails on List when right side is empty

Remove .DefaultIfEmpty() in

join rs in reserved.DefaultIfEmpty()

The reason why remove .DefaultIfEmpty() as:

public static System.Collections.Generic.IEnumerable<TSource> DefaultIfEmpty<TSource> (this System.Collections.Generic.IEnumerable<TSource> source, TSource defaultValue);

Returns

IEnumerable<TSource>
An IEnumerable that contains defaultValue if source is empty; otherwise, source.

Since you didn't pass defaultValue to .DefaultIfEmpty(), it will return null when reserved is empty list.

And select r since you want to return data from the LEFT table.

var leftOuterJoin = from r in received
join rs in reserved
on new { a = r.ProductId, b = r.WarehouseSectionId } equals new { a = rs.ProductId, b = rs.WarehouseSectionId } into joinedL
from rs in joinedL.DefaultIfEmpty()
select r;

Sample program


Updated:

In case you are accessing RIGHT table (rs), you need to do null checking for rs first and next handling for null case.

How does LINQ's left-join `join ... into` and `DefaultIfEmpty()` work?

Assuming we're talking about LINQ to Objects, DefaultIfEmpty will be evaluated once per element in the result. It will be evaluated on the sequence which is the group of values matching the "left" part of the join. So if we have:

from x in foo
join y in bar into z
let g = z.DefaultIfEmpty()
select new { x, g.Count() }

then for each x value, there will be an invocation of DefaultIfEmpty. For non-empty sequences, that will just pass values through. For empty sequences, the default value is returned (once) instead.

See my Edulinq blog post on it for more information.



Related Topics



Leave a reply



Submit