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.
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.
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
Is the C# Compiler Smart Enough to Optimize This Code
Use Dependency Injection in Static Class
Windows Forms Graphic Issue on Windows 10 Os
Discovering Derived Types Using Reflection
Auto Versioning in Visual Studio 2017 (.Net Core)
Sending and Receiving Data Over a Network Using Tcpclient
Differencebetween the Override and New Keywords in C#
In C#, How to Cast a List<Child> to List<Parent>
Winforms Issue - Error Creating Window Handle
Parent Control Mouse Enter/Leave Events with Child Controls
A Dictionary Object That Uses Ranges of Values for Keys
Dynamically Added Dropdownlists Are Not Firing Selectedindexchanged Event
String Interpolation with Format Variable
Datetime Tostring Issue with Formatting Months with "Mm" Specifier
Restsharp Simple Complete Example