I'm trying to enhance a person object by doing a join. I want to do a left outer join on firstname and lastname. Then I want to update the person object with a method (this method returns a person object back) I have available and select from there.
The issue I have here is that there is a null reference exception and I'm not sure how to prevent that. If I remove the DefaultIfEmpty I get an inner join but obviously I want the left outer. I know typically you would want to handle nulls, but I'm unsure how to properly do that in this situation.
person = from p in person
join epd in enhancedPersonData
on new { p.firstname, p.lastname} equals new { epd.firstname, epd.lastname} into epdJoin
from epdj in epdJoin.DefaultIfEmpty()
select p.UpdatePerson(epdj);
I've tried the below but it is just an inner join:
person = from p in person
join epd in enhancedPersonData
on new { p.firstname, p.lastname} equals new { epd.firstname, epd.lastname}
select p.UpdatePerson(epd);
Person:
public class Person
{
public string Firstname{ get; set; }
public string Lastname{ get; set; }
public string Address{ get; set; }
public Person(string firstname, string lastname){
Firstname = firstname;
Lastname = lastname;
}
}
UpdatePerson:
public static Person UpdatePerson (this Person schema,
EnhancedPersonData enhancedPersonData)
{
if (!string.IsNullOrEmpty(enhancedPersonData.Address))
{
schema.Address = enhancedPersonData.Address;
}
}
Solution:
UpdatePerson:
public static Person UpdatePerson (this Person schema,
EnhancedPersonData enhancedPersonData)
{
if (!string.IsNullOrEmpty(enhancedPersonData?.Address))
{
schema.Address = enhancedPersonData.Address;
}
}
Join Code:
person = from p in person
join epd in enhancedPersonData
on new { p.firstname, p.lastname} equals new { epd.firstname, epd.lastname} into epdJoin
from epdj in epdJoin.DefaultIfEmpty()
select p.UpdatePerson(epdj);
CodePudding user response:
If you are using a left join, then epdj
will be null
if there is no matching person in enhancedPersonData
.
What is the point in updating a person with null: p.UpdatePerson(null);
?
Since a class is a reference type, the original person collection will automatically contain the updated persons. It makes no sense to re-assign the returned persons to it. You can safely discard the result of the query, then the left join is no more necessary
_ = from p in person
join epd in enhancedPersonData
on new { p.firstname, p.lastname} equals new { epd.firstname, epd.lastname}
select p.UpdatePerson(epd);
Note that in C# _
is a discard.
Solutions
Remove null reference exception
After you have posted your code, I see where your null reference exception occurs. It is in the line
if (!string.IsNullOrEmpty(enhancedPersonData.Address))
If you use left join, then
enhancedPersonData
can benull
. Therefore change the line toif (!String.IsNullOrEmpty(enhancedPersonData?.Address))
Convert IEnumerable to List
Other possible solution: Since
person
is anIEnumerable<Person>
, it is unknown to me what the real data source is. Is it a collection or the result of a database query? In the latter case my approach (no left join, assign to_
) won't work. However, you can make it work by declaringperson
as aList<Person>
instead. Because otherwise, the real data source will be required every time you enumerate theIEnumerable<Person> person
.
Note that an IEnumerable<T>
is not a collection. It provides a means to enumerate a collection or a data source.
Also, the assignment in UpdatePerson
should be
schema.Address = enhancedPersonData.Address; // With a lower case enhancedPersonData
instead of
schema.Address = EnhancedPersonData.Address;
otherwise you might be accessing a static property, which of course would have the same value for all objects.