views:

76

answers:

3

I have the below LINQ that is returning zero IF there aren't any Addresses(Inner Join). How would I make this an Outer Join and then only Take(1)?

var results = query.Join(
                DB.tblAddresses.Where(t => t.AddressTypeID == 'm' || t.AddressTypeID == 'b').OrderByDescending(x => x.AddressTypeID),
                p => p.PersonID,
                a => a.PersonID,
                (p, a) =>
                new
                    {
                        p.PersonID,
                        p.LastName,
                        p.FirstName,
                        p.MiddleName,
                        p.SSN,
                        p.BirthDate,
                        p.DeathDate,
                        AddressLine1 = a.AddressLine1 ?? string.Empty
                });

            return results.CopyLinqToDataTable();
A: 

Use DefaultIfEmpty. Take a look at http://social.msdn.microsoft.com/Forums/en-US/linqtosql/thread/b285be6a-3324-4b16-89cd-856190090701

Kamyar
I tried this like so --> ` DB.tblAddresses.Where(t => t.AddressTypeID == 'm' || t.AddressTypeID == 'b').OrderByDescending(x => x.AddressTypeID).DefaultIfEmpty(),` to no avail. Thanks for the ideas though.
Refracted Paladin
To clarify, it still returns nothing if Address row is missing.
Refracted Paladin
+1  A: 
query
    .SelectMany (  
      p => DB.tblAddresses.Where((t => t.AddressTypeID == 'm' || t.AddressTypeID == 'b') && t.PersonID == p.PersonID)**.DefaultIfEmpty()**,
      (p, t) =>
         new 
         {
             p.PersonID,  
                        p.LastName,  
                        p.FirstName,  
                        p.MiddleName,  
                        p.SSN,  
                        p.BirthDate,  
                        p.DeathDate  
            Addressline1 = (t == null ? null : t.AddressLine1)
         }  

)

Kamyar
For each `p`, `t` would be the same, which is not what is wanted. Also, `t.Addressline1` would throw if the `t` was `null` (which would happen if the collection generated on the second row would be empty).
svick
use: Addressline1 = (t == null ? null : t.AddressLine1)
Kamyar
Yeah, that fixes the second problem, but the first one is much bigger.
svick
Got it. Run the updated query. (And please remove the vote down if it works :p)
Kamyar
Thanks for the persistence, I will give your solution a try as well. As for the down vote, wasn't me so I can't undo it. If it works I will definitely +1 you though.
Refracted Paladin
Yeah, this would do the outer join if you fixed the syntax error you made there.
svick
+1  A: 

Use GroupJoin:

var results = query.GroupJoin(
    addresses,
    p => p.PersonID,
    a => a.PersonID,
    (p, a) =>
    new
    {
        p.PersonID,
        p.LastName,
        p.FirstName,
        p.MiddleName,
        p.SSN,
        p.BirthDate,
        p.DeathDate,
        AddressLine1 = a.Any()
            ? (a.First().AddressLine1 ?? string.Empty)
            : null
    });
svick