Search code examples
c#-4.0entity-framework-4.3

Converting a LEFT OUTER JOIN to Entity Framework


Here is a SQL Query I want to convert to EF4.3

        command = database.GetSqlStringCommand(@"
                                select 
                                    H.AUTHENTICATION_ID, 
                                    USERNAME, 
                                    PERMISSIONS,
                                    ORGANIZATION_IDENTIFIER, 
                                    O.ORGANIZATION_ID 
                                from 
                                    AUTHENTICATION H 
                                        left join [AUTHORIZATION] T on H.AUTHENTICATION_ID=T.AUTHENTICATION_ID 
                                        join ORGANIZATION O on O.ORGANIZATION_ID = T.ORGANIZATION_ID
                                order by H.AUTHENTICATION_ID");

Here is the best LINQ I could come up with:

        var query = from h in context.Authentications
            join t in context.Authorizations on h.AuthenticationId equals t.Authentications.AuthenticationId 
            join o in context.Organizations on t.Organizations.OrganizationId equals o.OrganizationId
            orderby
            h.AuthenticationId
            select new
            { AUTHENTICATION_ID = (Int16?)h.AuthenticationId,
                h.Username,
                t.Permissions,
                o.OrganizationIdentifier,
                OrganizationID = (Int16?)o.OrganizationId
            };

I know i need to merge my first join (between Authorizations & Authentications) into, lets say x and apply DefaultIfEmpty but can't make out the syntax.

EDIT: Image for clarification: Data Model

Any help will be highly appreciated. Regards.


Solution

  • The basic syntax for a "left join" in Linq is like this:

    from x in table1
    join y in table2 on x.id equals y.id into jointable
    from z in jointable.DefaultIfEmpty()
    select new
    {
      x.Field1, 
      x.Field2,
      x.Field3,
      Field4 = z == null ? 0 : z.Field4
    };
    

    In your case, I'm a little confused because the entity relations you seem to be using in your Linq don't match the ones implied by your SQL; are the relationships here zero-or-one, zero-or-many, one-to-one, etc? Specifically, you're doing this:

    from h in context.Authentications
    join t in context.Authorizations on h.AuthenticationId equals t.Authentications.AuthenticationId
    

    but your SQL implies that "Authentication" is the parent here with zero-or-more "Authorization" children, not the other way around, which would be more like:

    from h in context.Authentications
    from t in h.Authorizations.DefaultIfEmpty()
    

    If you can give us a better idea of the data model and what data you expect to get out of it we can more easily explain how that query would look in Linq. Assuming that your relationships match what is implied by the SQL, you should be able to get what you want using the following Linq queries:

    var query = from h in context.Authentications
                from t in h.Authorizations.DefaultIfEmpty()
                select new
                {
                    h.AuthenticationId,
                    h.Username,
                    Permissions = t == null ? null : t.Permissions,
                    Organizations = t == null ? new EntitySet<Organization>() : t.Organizations
                };
    
    var query2 = from x in query
                 from o in x.organizations.DefaultIfEmpty()
                 select new
                 {
                     AUTHENTICATION_ID = (short?)x.AuthenticationId,
                     x.Username,
                     x.Permissions,
                     OrganizationIdentifier = o == null ? null : o.OrganizationIdentifier,
                     OrganizationID = o == null ? (short?)null : o.OrganizationID 
                 };