Meeting the needs of your business from a distance

Examining Entity Framework’s SQL Generation

by mark shiffer 30. June 2010 16:00

I am just getting started with this, but so far I am less than impressed with the SQL that is being generated by Entity Framework. The following is an example of a query that is generated by Entity Framework for a system that I am currently working on.

   1: SELECT 
   2: [UnionAll4].[C2] AS [C1], 
   3: ...
   4: [UnionAll4].[C590] AS [C590]
   5: FROM  (SELECT 
   6:     [UnionAll2].[C1] AS [C1], 
   7:         ...
   8:     [UnionAll2].[C590] AS [C590]
   9:     FROM  (SELECT 
  10:         [UnionAll1].[C1] AS [C1], 
  11:         ...
  12:         [UnionAll1].[C547] AS [C590]
  13:         FROM  (SELECT 
  14:             CASE WHEN ([Extent5].[Id] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C1], 
  15:             [Extent2].[Id] AS [Id], 
  16:             [Extent3].[Id] AS [Id1], 
  17:             0 AS [C2], 
  18:             '0X0X0X0X' AS [C3], 
  19:             0 AS [C4], 
  20:             [Extent1].[Id] AS [Id2], 
  21:             [Extent1].[ModifiedBy] AS [ModifiedBy], 
  22:             [Extent1].[LastModified] AS [LastModified], 
  23:             [Extent1].[TaxId] AS [TaxId], 
  24:             [Extent1].[Version] AS [Version], 
  25:             [Extent2].[LastName] AS [LastName], 
  26:             [Extent2].[FirstName] AS [FirstName], 
  27:             [Extent2].[BirthDate] AS [BirthDate], 
  28:             [Extent2].[MiddleName] AS [MiddleName], 
  29:             [Extent2].[Gender] AS [Gender], 
  30:             [Extent2].[PreferredName] AS [PreferredName], 
  31:             [Extent3].[SrsStartDate] AS [SrsStartDate], 
  32:             [Extent3].[VacationBaseDate] AS [VacationBaseDate], 
  33:             [Extent3].[CredibleServiceDate] AS [CredibleServiceDate], 
  34:             [Extent3].[ContinuousServiceDate] AS [ContinuousServiceDate], 
  35:             [Extent3].[TerminationDate] AS [TerminationDate], 
  36:             [Extent3].[MonthlySalary] AS [MonthlySalary], 
  37:             [Extent3].[PayStep] AS [PayStep], 
  38:             [Extent3].[IsMeritComp] AS [IsMeritComp], 
  39:             [Extent3].[SeniorityDate] AS [SeniorityDate], 
  40:             [Extent3].[WorkScheduleTypeId] AS [WorkScheduleTypeId], 
  41:             [Extent3].[SupervisorEmployeeId] AS [SupervisorEmployeeId], 
  42:             CAST(NULL AS varchar(1)) AS [C5], 
  43:             CAST(NULL AS varchar(1)) AS [C6], 
  44:             CAST(NULL AS varchar(1)) AS [C7], 
  45:             CAST(NULL AS uniqueidentifier) AS [C8], 
  46:             CAST(NULL AS uniqueidentifier) AS [C9], 
  47:             CAST(NULL AS varbinary(1)) AS [C10], 
  48:             CAST(NULL AS varchar(1)) AS [C11], 
  49:             CAST(NULL AS varchar(1)) AS [C12], 
  50:             CAST(NULL AS varchar(1)) AS [C13], 
  51:             CAST(NULL AS varchar(1)) AS [C14], 
  52:             CAST(NULL AS uniqueidentifier) AS [C15], 
  53:             CAST(NULL AS uniqueidentifier) AS [C16], 
  54:             ...
  55:             CAST(NULL AS varbinary(1)) AS [C53], 
  56:             CASE WHEN ([Extent4].[Id] IS NULL) THEN CAST(NULL AS varchar(1)) ELSE '0X3X' END AS [C54], 
  57:             CASE WHEN ([Extent4].[Id] IS NULL) THEN CAST(NULL AS int) ELSE 4 END AS [C55], 
  58:             [Extent4].[Id] AS [Id3], 
  59:             [Extent4].[ModifiedBy] AS [ModifiedBy1], 
  60:             [Extent4].[LastModified] AS [LastModified1], 
  61:             CAST(NULL AS varchar(1)) AS [C56], 
  62:             ...
  63:             CAST(NULL AS varbinary(1)) AS [C89], 
  64:             [Extent4].[Sequence] AS [Sequence], 
  65:             [Extent4].[TitleId] AS [TitleId], 
  66:             [Extent4].[AgencyId] AS [AgencyId], 
  67:             [Extent4].[SectionId] AS [SectionId], 
  68:             [Extent4].[EqualEmploymentOpportunityCodeId] AS [EqualEmploymentOpportunityCodeId], 
  69:             [Extent4].[BargainingUnitCodeId] AS [BargainingUnitCodeId], 
  70:             [Extent4].[Version] AS [Version1], 
  71:             CAST(NULL AS datetime2) AS [C90], 
  72:             ...
  73:             CAST(NULL AS varbinary(1)) AS [C116], 
  74:             CASE WHEN ([Extent5].[Id] IS NULL) THEN CAST(NULL AS varchar(1)) ELSE '0X1X' END AS [C117], 
  75:             CASE WHEN ([Extent5].[Id] IS NULL) THEN CAST(NULL AS int) ELSE 5 END AS [C118], 
  76:             [Extent5].[Id] AS [Id4], 
  77:             [Extent5].[ModifiedBy] AS [ModifiedBy2], 
  78:             [Extent5].[LastModified] AS [LastModified2], 
  79:             CAST(NULL AS varchar(1)) AS [C119], 
  80:             ...
  81:             CAST(NULL AS uniqueidentifier) AS [C137], 
  82:             [Extent5].[CountryCode] AS [CountryCode], 
  83:             ...
  84:             CAST(NULL AS varbinary(1)) AS [C547]
  85:             FROM     [dbo].[Orgsons] AS [Extent1]
  86:             INNER JOIN [dbo].[Orgsons_Person] AS [Extent2] ON [Extent1].[Id] = [Extent2].[Id]
  87:             INNER JOIN [dbo].[Orgsons_Employee] AS [Extent3] ON [Extent1].[Id] = [Extent3].[Id]
  88:             LEFT OUTER JOIN [dbo].[Positions] AS [Extent4] ON [Extent3].[Position_Id] = [Extent4].[Id]
  89:             LEFT OUTER JOIN [dbo].[PhoneNumbers] AS [Extent5] ON [Extent1].[Id] = [Extent5].[OrgsonId]
  90:             WHERE [Extent1].[Id] = '4F65BC85-06FD-4CC7-BB2B-95F2536EF132'
  91:         UNION ALL
  92:             SELECT 
  93:             2 AS [C1], 
  94:             [Extent7].[Id] AS [Id], 
  95:             [Extent8].[Id] AS [Id1], 
  96:             0 AS [C2], 
  97:             '0X0X0X0X' AS [C3], 
  98:             0 AS [C4], 
  99:             [Extent6].[Id] AS [Id2], 
 100:             [Extent6].[ModifiedBy] AS [ModifiedBy], 
 101:             [Extent6].[LastModified] AS [LastModified], 
 102:             [Extent6].[TaxId] AS [TaxId], 
 103:             [Extent6].[Version] AS [Version], 
 104:             [Extent7].[LastName] AS [LastName], 
 105:             [Extent7].[FirstName] AS [FirstName], 
 106:             [Extent7].[BirthDate] AS [BirthDate], 
 107:             [Extent7].[MiddleName] AS [MiddleName], 
 108:             [Extent7].[Gender] AS [Gender], 
 109:             [Extent7].[PreferredName] AS [PreferredName], 
 110:             [Extent8].[SrsStartDate] AS [SrsStartDate], 
 111:             [Extent8].[VacationBaseDate] AS [VacationBaseDate], 
 112:             [Extent8].[CredibleServiceDate] AS [CredibleServiceDate], 
 113:             [Extent8].[ContinuousServiceDate] AS [ContinuousServiceDate], 
 114:             [Extent8].[TerminationDate] AS [TerminationDate], 
 115:             [Extent8].[MonthlySalary] AS [MonthlySalary], 
 116:             [Extent8].[PayStep] AS [PayStep], 
 117:             [Extent8].[IsMeritComp] AS [IsMeritComp], 
 118:             [Extent8].[SeniorityDate] AS [SeniorityDate], 
 119:             [Extent8].[WorkScheduleTypeId] AS [WorkScheduleTypeId], 
 120:             [Extent8].[SupervisorEmployeeId] AS [SupervisorEmployeeId], 
 121:             CAST(NULL AS varchar(1)) AS [C5], 
 122:             ...
 123:             CAST(NULL AS varbinary(1)) AS [C53], 
 124:             CASE WHEN ([Extent9].[Id] IS NULL) THEN CAST(NULL AS varchar(1)) ELSE '0X3X' END AS [C54], 
 125:             CASE WHEN ([Extent9].[Id] IS NULL) THEN CAST(NULL AS int) ELSE 4 END AS [C55], 
 126:             [Extent9].[Id] AS [Id3], 
 127:             [Extent9].[ModifiedBy] AS [ModifiedBy1], 
 128:             [Extent9].[LastModified] AS [LastModified1], 
 129:             CAST(NULL AS varchar(1)) AS [C56], 
 130:             ...
 131:             CAST(NULL AS varbinary(1)) AS [C89], 
 132:             [Extent9].[Sequence] AS [Sequence], 
 133:             [Extent9].[TitleId] AS [TitleId], 
 134:             [Extent9].[AgencyId] AS [AgencyId], 
 135:             [Extent9].[SectionId] AS [SectionId], 
 136:             [Extent9].[EqualEmploymentOpportunityCodeId] AS [EqualEmploymentOpportunityCodeId], 
 137:             [Extent9].[BargainingUnitCodeId] AS [BargainingUnitCodeId], 
 138:             [Extent9].[Version] AS [Version1], 
 139:             CAST(NULL AS datetime2) AS [C90], 
 140:             ...
 141:             CAST(NULL AS varbinary(1)) AS [C216], 
 142:             [Extent10].[Street1] AS [Street1], 
 143:             [Extent10].[Street2] AS [Street2], 
 144:             [Extent10].[City] AS [City], 
 145:             [Extent10].[ZipCode] AS [ZipCode], 
 146:             [Extent10].[OrgsonId] AS [OrgsonId], 
 147:             [Extent10].[AddressTypeId] AS [AddressTypeId], 
 148:             [Extent10].[StateId] AS [StateId], 
 149:             [Extent10].[CountryId] AS [CountryId], 
 150:             [Extent10].[Version] AS [Version2], 
 151:             CAST(NULL AS varchar(1)) AS [C217], 
 152:             ... 
 153:             CAST(NULL AS varbinary(1)) AS [C544]
 154:             FROM     [dbo].[Orgsons] AS [Extent6]
 155:             INNER JOIN [dbo].[Orgsons_Person] AS [Extent7] ON [Extent6].[Id] = [Extent7].[Id]
 156:             INNER JOIN [dbo].[Orgsons_Employee] AS [Extent8] ON [Extent6].[Id] = [Extent8].[Id]
 157:             LEFT OUTER JOIN [dbo].[Positions] AS [Extent9] ON [Extent8].[Position_Id] = [Extent9].[Id]
 158:             INNER JOIN [dbo].[Addresses] AS [Extent10] ON [Extent6].[Id] = [Extent10].[OrgsonId]
 159:             WHERE [Extent6].[Id] = '4F65BC85-06FD-4CC7-BB2B-95F2536EF132') AS [UnionAll1]
 160:     UNION ALL
 161:         SELECT 
 162:         3 AS [C1], 
 163:         [Extent12].[Id] AS [Id], 
 164:         [Extent13].[Id] AS [Id1], 
 165:         0 AS [C2], 
 166:         '0X0X0X0X' AS [C3], 
 167:         0 AS [C4], 
 168:         [Extent11].[Id] AS [Id2], 
 169:         [Extent11].[ModifiedBy] AS [ModifiedBy], 
 170:         [Extent11].[LastModified] AS [LastModified], 
 171:         [Extent11].[TaxId] AS [TaxId], 
 172:         [Extent11].[Version] AS [Version], 
 173:         [Extent12].[LastName] AS [LastName], 
 174:         [Extent12].[FirstName] AS [FirstName], 
 175:         [Extent12].[BirthDate] AS [BirthDate], 
 176:         [Extent12].[MiddleName] AS [MiddleName], 
 177:         [Extent12].[Gender] AS [Gender], 
 178:         [Extent12].[PreferredName] AS [PreferredName], 
 179:         [Extent13].[SrsStartDate] AS [SrsStartDate], 
 180:         [Extent13].[VacationBaseDate] AS [VacationBaseDate], 
 181:         [Extent13].[CredibleServiceDate] AS [CredibleServiceDate], 
 182:         [Extent13].[ContinuousServiceDate] AS [ContinuousServiceDate], 
 183:         [Extent13].[TerminationDate] AS [TerminationDate], 
 184:         [Extent13].[MonthlySalary] AS [MonthlySalary], 
 185:         [Extent13].[PayStep] AS [PayStep], 
 186:         [Extent13].[IsMeritComp] AS [IsMeritComp], 
 187:         [Extent13].[SeniorityDate] AS [SeniorityDate], 
 188:         [Extent13].[WorkScheduleTypeId] AS [WorkScheduleTypeId], 
 189:         [Extent13].[SupervisorEmployeeId] AS [SupervisorEmployeeId], 
 190:         CAST(NULL AS varchar(1)) AS [C5], 
 191:         ...
 192:         CAST(NULL AS varbinary(1)) AS [C53], 
 193:         CASE WHEN ([Extent14].[Id] IS NULL) THEN CAST(NULL AS varchar(1)) ELSE '0X3X' END AS [C54], 
 194:         CASE WHEN ([Extent14].[Id] IS NULL) THEN CAST(NULL AS int) ELSE 4 END AS [C55], 
 195:         [Extent14].[Id] AS [Id3], 
 196:         [Extent14].[ModifiedBy] AS [ModifiedBy1], 
 197:         [Extent14].[LastModified] AS [LastModified1], 
 198:         CAST(NULL AS varchar(1)) AS [C56], 
 199:         ...
 200:         CAST(NULL AS varbinary(1)) AS [C89], 
 201:         [Extent14].[Sequence] AS [Sequence], 
 202:         [Extent14].[TitleId] AS [TitleId], 
 203:         [Extent14].[AgencyId] AS [AgencyId], 
 204:         [Extent14].[SectionId] AS [SectionId], 
 205:         [Extent14].[EqualEmploymentOpportunityCodeId] AS [EqualEmploymentOpportunityCodeId], 
 206:         [Extent14].[BargainingUnitCodeId] AS [BargainingUnitCodeId], 
 207:         [Extent14].[Version] AS [Version1], 
 208:         CAST(NULL AS datetime2) AS [C90], 
 209:         ...
 210:         CAST(NULL AS varbinary(1)) AS [C262], 
 211:         '0X4X' AS [C263], 
 212:         10 AS [C264], 
 213:         [Extent15].[Id] AS [Id4], 
 214:         [Extent15].[ModifiedBy] AS [ModifiedBy2], 
 215:         [Extent15].[LastModified] AS [LastModified2], 
 216:         CAST(NULL AS varchar(1)) AS [C265], 
 217:         ...
 218:         CAST(NULL AS varbinary(1)) AS [C305], 
 219:         [Extent15].[SentDate] AS [SentDate], 
 220:         [Extent15].[ReturnedDate] AS [ReturnedDate], 
 221:         [Extent15].[EmployeeId] AS [EmployeeId], 
 222:         [Extent15].[EvaluationTypeId] AS [EvaluationTypeId], 
 223:         [Extent15].[Version] AS [Version2], 
 224:         CAST(NULL AS datetime2) AS [C306], 
 225:         ...
 226:         CAST(NULL AS varbinary(1)) AS [C548]
 227:         FROM     [dbo].[Orgsons] AS [Extent11]
 228:         INNER JOIN [dbo].[Orgsons_Person] AS [Extent12] ON [Extent11].[Id] = [Extent12].[Id]
 229:         INNER JOIN [dbo].[Orgsons_Employee] AS [Extent13] ON [Extent11].[Id] = [Extent13].[Id]
 230:         LEFT OUTER JOIN [dbo].[Positions] AS [Extent14] ON [Extent13].[Position_Id] = [Extent14].[Id]
 231:         INNER JOIN [dbo].[Evaluations] AS [Extent15] ON [Extent11].[Id] = [Extent15].[EmployeeId]
 232:         WHERE [Extent11].[Id] = '4F65BC85-06FD-4CC7-BB2B-95F2536EF132') AS [UnionAll2]
 233: UNION ALL
 234:     SELECT 
 235:     4 AS [C1], 
 236:     [Project6].[Id1] AS [Id], 
 237:     [Project6].[Id2] AS [Id1], 
 238:     [Project6].[C2] AS [C2], 
 239:     [Project6].[C1] AS [C3], 
 240:     [Project6].[C2] AS [C4], 
 241:     [Project6].[Id] AS [Id2], 
 242:     [Project6].[ModifiedBy] AS [ModifiedBy], 
 243:     [Project6].[LastModified] AS [LastModified], 
 244:     [Project6].[TaxId] AS [TaxId], 
 245:     [Project6].[Version] AS [Version], 
 246:     [Project6].[LastName] AS [LastName], 
 247:     [Project6].[FirstName] AS [FirstName], 
 248:     [Project6].[BirthDate] AS [BirthDate], 
 249:     [Project6].[MiddleName] AS [MiddleName], 
 250:     [Project6].[Gender] AS [Gender], 
 251:     [Project6].[PreferredName] AS [PreferredName], 
 252:     [Project6].[SrsStartDate] AS [SrsStartDate], 
 253:     [Project6].[VacationBaseDate] AS [VacationBaseDate], 
 254:     [Project6].[CredibleServiceDate] AS [CredibleServiceDate], 
 255:     [Project6].[ContinuousServiceDate] AS [ContinuousServiceDate], 
 256:     [Project6].[TerminationDate] AS [TerminationDate], 
 257:     [Project6].[MonthlySalary] AS [MonthlySalary], 
 258:     [Project6].[PayStep] AS [PayStep], 
 259:     [Project6].[IsMeritComp] AS [IsMeritComp], 
 260:     [Project6].[SeniorityDate] AS [SeniorityDate], 
 261:     [Project6].[WorkScheduleTypeId] AS [WorkScheduleTypeId], 
 262:     [Project6].[SupervisorEmployeeId] AS [SupervisorEmployeeId], 
 263:     [Project6].[C3] AS [C5], 
 264:     ...
 265:     [Project6].[Id3] AS [Id3], 
 266:     [Project6].[ModifiedBy1] AS [ModifiedBy1], 
 267:     [Project6].[LastModified1] AS [LastModified1], 
 268:     [Project6].[C54] AS [C56], 
 269:     ... 
 270:     [Project6].[C86] AS [C88], 
 271:     [Project6].[C87] AS [C89], 
 272:     [Project6].[Sequence] AS [Sequence], 
 273:     [Project6].[TitleId] AS [TitleId], 
 274:     [Project6].[AgencyId] AS [AgencyId], 
 275:     [Project6].[SectionId] AS [SectionId], 
 276:     [Project6].[EqualEmploymentOpportunityCodeId] AS [EqualEmploymentOpportunityCodeId], 
 277:     [Project6].[BargainingUnitCodeId] AS [BargainingUnitCodeId], 
 278:     [Project6].[Version1] AS [Version1], 
 279:     [Project6].[C88] AS [C90], 
 280:     ...     
 281:     CAST(NULL AS varbinary(1)) AS [C335], 
 282:     ...
 283:     [UnionAll3].[C199] AS [C556]
 284:     FROM   (SELECT 
 285:         [Extent16].[Id] AS [Id], 
 286:         [Extent16].[TaxId] AS [TaxId], 
 287:         [Extent16].[Version] AS [Version], 
 288:         [Extent16].[ModifiedBy] AS [ModifiedBy], 
 289:         [Extent16].[LastModified] AS [LastModified], 
 290:         [Extent17].[LastName] AS [LastName], 
 291:         [Extent17].[FirstName] AS [FirstName], 
 292:         [Extent17].[BirthDate] AS [BirthDate], 
 293:         [Extent17].[MiddleName] AS [MiddleName], 
 294:         [Extent17].[Gender] AS [Gender], 
 295:         [Extent17].[PreferredName] AS [PreferredName], 
 296:         [Extent17].[Id] AS [Id1], 
 297:         [Extent18].[SrsStartDate] AS [SrsStartDate], 
 298:         [Extent18].[VacationBaseDate] AS [VacationBaseDate], 
 299:         [Extent18].[CredibleServiceDate] AS [CredibleServiceDate], 
 300:         [Extent18].[ContinuousServiceDate] AS [ContinuousServiceDate], 
 301:         [Extent18].[TerminationDate] AS [TerminationDate], 
 302:         [Extent18].[MonthlySalary] AS [MonthlySalary], 
 303:         [Extent18].[PayStep] AS [PayStep], 
 304:         [Extent18].[IsMeritComp] AS [IsMeritComp], 
 305:         [Extent18].[SeniorityDate] AS [SeniorityDate], 
 306:         [Extent18].[WorkScheduleTypeId] AS [WorkScheduleTypeId], 
 307:         [Extent18].[SupervisorEmployeeId] AS [SupervisorEmployeeId], 
 308:         [Extent18].[Id] AS [Id2], 
 309:         '0X0X0X0X' AS [C1], 
 310:         0 AS [C2], 
 311:         CAST(NULL AS varchar(1)) AS [C3], 
 312:         ... 
 313:         CAST(NULL AS varbinary(1)) AS [C51], 
 314:         [Extent19].[Id] AS [Id3], 
 315:         [Extent19].[Sequence] AS [Sequence], 
 316:         [Extent19].[TitleId] AS [TitleId], 
 317:         [Extent19].[AgencyId] AS [AgencyId], 
 318:         [Extent19].[SectionId] AS [SectionId], 
 319:         [Extent19].[EqualEmploymentOpportunityCodeId] AS [EqualEmploymentOpportunityCodeId], 
 320:         [Extent19].[BargainingUnitCodeId] AS [BargainingUnitCodeId], 
 321:         [Extent19].[Version] AS [Version1], 
 322:         [Extent19].[ModifiedBy] AS [ModifiedBy1], 
 323:         [Extent19].[LastModified] AS [LastModified1], 
 324:         CASE WHEN ([Extent19].[Id] IS NULL) THEN CAST(NULL AS varchar(1)) ELSE '0X3X' END AS [C52], 
 325:         CASE WHEN ([Extent19].[Id] IS NULL) THEN CAST(NULL AS int) ELSE 4 END AS [C53], 
 326:         CAST(NULL AS varchar(1)) AS [C54], 
 327:         ... 
 328:         CAST(NULL AS varbinary(1)) AS [C114]
 329:         FROM    [dbo].[Orgsons] AS [Extent16]
 330:         INNER JOIN [dbo].[Orgsons_Person] AS [Extent17] ON [Extent16].[Id] = [Extent17].[Id]
 331:         INNER JOIN [dbo].[Orgsons_Employee] AS [Extent18] ON [Extent16].[Id] = [Extent18].[Id]
 332:         LEFT OUTER JOIN [dbo].[Positions] AS [Extent19] ON [Extent18].[Position_Id] = [Extent19].[Id]
 333:         WHERE [Extent16].[Id] = '4F65BC85-06FD-4CC7-BB2B-95F2536EF132' ) AS [Project6]
 334:     CROSS APPLY  (SELECT 
 335:         CASE WHEN ([Extent21].[Id] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C1], 
 336:         12 AS [C2], 
 337:         '0X5X' AS [C3], 
 338:         12 AS [C4], 
 339:         [Extent20].[Id] AS [Id], 
 340:         [Extent20].[ModifiedBy] AS [ModifiedBy], 
 341:         [Extent20].[LastModified] AS [LastModified], 
 342:         CAST(NULL AS varchar(1)) AS [C5], 
 343:         ... 
 344:         CAST(NULL AS varbinary(1)) AS [C61], 
 345:         CASE WHEN ([Extent21].[Id] IS NULL) THEN CAST(NULL AS varchar(1)) ELSE '0X6X' END AS [C62], 
 346:         CASE WHEN ([Extent21].[Id] IS NULL) THEN CAST(NULL AS int) ELSE 14 END AS [C63], 
 347:         [Extent21].[Id] AS [Id1], 
 348:         [Extent21].[ModifiedBy] AS [ModifiedBy1], 
 349:         [Extent21].[LastModified] AS [LastModified1], 
 350:         CAST(NULL AS varchar(1)) AS [C64], 
 351:         ... 
 352:         CAST(NULL AS varbinary(1)) AS [C120], 
 353:         [Extent21].[Description] AS [Description], 
 354:         [Extent21].[Created] AS [Created1], 
 355:         [Extent21].[CreatedBy] AS [CreatedBy], 
 356:         [Extent21].[LeaveOfAbsenceId] AS [LeaveOfAbsenceId], 
 357:         [Extent21].[Version] AS [Version1], 
 358:         CAST(NULL AS datetime2) AS [C121], 
 359:         ... 
 360:         CAST(NULL AS varbinary(1)) AS [C199]
 361:         FROM  [dbo].[LeaveOfAbsences] AS [Extent20]
 362:         LEFT OUTER JOIN [dbo].[Comments] AS [Extent21] ON [Extent20].[Id] = [Extent21].[LeaveOfAbsenceId]
 363:         WHERE ([Project6].[C2] = 0) AND ([Project6].[Id] = [Extent20].[EmployeeId])
 364:     UNION ALL
 365:         SELECT 
 366:         2 AS [C1], 
 367:         12 AS [C2], 
 368:         '0X5X' AS [C3], 
 369:         12 AS [C4], 
 370:         [Extent22].[Id] AS [Id], 
 371:         [Extent22].[ModifiedBy] AS [ModifiedBy], 
 372:         [Extent22].[LastModified] AS [LastModified], 
 373:         CAST(NULL AS varchar(1)) AS [C5], 
 374:         ... 
 375:         CAST(NULL AS varbinary(1)) AS [C50], 
 376:         [Extent22].[RequestReceivedDate] AS [RequestReceivedDate], 
 377:         [Extent22].[PacketSentDate] AS [PacketSentDate], 
 378:         [Extent22].[PacketReceivedDate] AS [PacketReceivedDate], 
 379:         [Extent22].[ReviewSentDate] AS [ReviewSentDate], 
 380:         [Extent22].[ReviewReceivedDate] AS [ReviewReceivedDate], 
 381:         [Extent22].[ApprovedDate] AS [ApprovedDate], 
 382:         [Extent22].[EmployeeId] AS [EmployeeId], 
 383:         [Extent22].[Created] AS [Created], 
 384:         [Extent22].[LeaveTypeId] AS [LeaveTypeId], 
 385:         [Extent22].[LeaveStatusId] AS [LeaveStatusId], 
 386:         [Extent22].[Version] AS [Version], 
 387:         CAST(NULL AS varchar(1)) AS [C51], 
 388:         ...
 389:         CAST(NULL AS varbinary(1)) AS [C134], 
 390:         '0X7X' AS [C135], 
 391:         16 AS [C136], 
 392:         [Extent23].[Id] AS [Id1], 
 393:         [Extent23].[ModifiedBy] AS [ModifiedBy1], 
 394:         [Extent23].[LastModified] AS [LastModified1], 
 395:         CAST(NULL AS varchar(1)) AS [C137], 
 396:         ... 
 397:         CAST(NULL AS varbinary(1)) AS [C198], 
 398:         [Extent23].[StartDate] AS [StartDate], 
 399:         [Extent23].[StopDate] AS [StopDate], 
 400:         [Extent23].[DaysOff] AS [DaysOff], 
 401:         [Extent23].[Created] AS [Created1], 
 402:         [Extent23].[LeaveOfAbsenceId] AS [LeaveOfAbsenceId], 
 403:         [Extent23].[Version] AS [Version1]
 404:         FROM  [dbo].[LeaveOfAbsences] AS [Extent22]
 405:         INNER JOIN [dbo].[LeaveOutOfOffices] AS [Extent23] ON [Extent22].[Id] = [Extent23].[LeaveOfAbsenceId]
 406:         WHERE ([Project6].[C2] = 0) AND ([Project6].[Id] = [Extent22].[EmployeeId])) AS [UnionAll3]) AS [UnionAll4]
 407: ORDER BY [UnionAll4].[C2] ASC, [UnionAll4].[C3] ASC, [UnionAll4].[C7] ASC, [UnionAll4].[C80] ASC, [UnionAll4].[C1] ASC, [UnionAll4].[C373] ASC, [UnionAll4].[C444] ASC;

That amounts to almost 4800 lines of SQL (much of it repetitive and omitted above) for a simple retrieve of an employee by id with some related data! Wow, what can be said about that!

The following query does the same thing in about 20 lines and runs 3 times faster:

   1: SELECT 
   2:     * 
   3: FROM 
   4:     Orgsons_Employee e 
   5:         JOIN 
   6:     Orgsons_Person p ON (e.Id = p.Id) 
   7:         JOIN 
   8:     Orgsons o ON (o.Id = p.Id) 
   9:         LEFT JOIN 
  10:     PhoneNumbers pn ON (pn.OrgsonId = o.Id) 
  11:         LEFT JOIN 
  12:     Addresses a ON (a.OrgsonId = o.Id) 
  13:         LEFT JOIN 
  14:     Positions pos ON (e.Position_Id = pos.Id) 
  15:         LEFT JOIN 
  16:     Evaluations eval ON (eval.EmployeeId = e.Id) 
  17:         LEFT JOIN 
  18:     LeaveOfAbsences loa ON (loa.EmployeeId = e.Id) 
  19:         LEFT JOIN 
  20:     LeaveOutOfOffices loo ON (loo.LeaveOfAbsenceId = loa.Id) 
  21:         LEFT JOIN 
  22:     Comments c ON (c.LeaveOfAbsenceId = loa.Id) 
  23: WHERE 
  24:     e.Id = '4F65BC85-06FD-4CC7-BB2B-95F2536EF132';

The execution plan on SQL Server shows a drastic difference between the two. If I find any hidden tweaking options for this in Entity Framework I’ll update this post.

Tags: ,

Comments

7/1/2010 9:37:11 PM #

Kati Iceva

Hi Mark,

I’m sorry you have encountered this issue. While in the .NET 4.0 release we did numerous improvements to the TSQL generated when querying with the Entity Framework, we continue to work on further improvements for the next release.

Could you please give some more information on your scenario? What is the query that you tried? What is the shape of the model and the mapping strategy?

Thanks,
Kati Iceva,
Entity Framework Developer

Kati Iceva United States | Reply

7/6/2010 2:14:58 PM #

Mark Shiffer

Hi Kati. So the query is pretty straight forward, although, it has quite a few includes as you could see from the joins above. It breaks down to following in the end:
objectSet<Orgson>.OfType<Employee>().Include("PhoneNumbers", "Addresses", "Position", "Evaluations", "LeaveOfAbsences.Comments", "LeaveOfAbsences.LeaveOutOfOffices").Where(o => o.Id == id).SingleOrDefault();

Our mapping is done as Table Per Type. The above query relies upon a hierarchy of Orgson -> Person -> Employee, with each having a couple of off-shoot joins we are interested in. Phone/Addresses off of Orgson, Then Position, Evals, Leaves are off of Employee.


Thank you for your response Kati. If you have any suggestions on how we may be able to alter our approach to work better with EF, please let me know.

Thanks.

Mark Shiffer United States | Reply

7/7/2010 2:47:23 AM #

Kati Iceva

Thank you Mark for the additional information. The complexity of the output query comes from the number of includes. The Entity Framework expects one row per collection element from the database, thus the suggested query isn’t something we can currently produce.  We recognize this may be in issue in a scenario like this and are looking into it.

Does it make sense for your application to use less includes and to possibly do lazy loading?

Thanks,
Kati Iceva
Entity Framework Developer

Kati Iceva United States | Reply

7/12/2010 4:54:29 PM #

Mark Shiffer

Ultimately your suggestion was how I worked around this issue (i.e., reducing the number of includes, not lazy loading yet). However, there are scenarios where the includes are necessary.

I'm glad to hear that it is being worked on. When we get to more performance sensitive operations, it appears we will have to punt and not use Entity Framework though. That is a disappointment as abstracting the data storage logic for the business layer in a more domain friendly manner was a major reason for having an ORM in the first place. Lazy loading may help some, but I'm not sure it will overcome all of the performance issues with the errant SQL being generated.

Mark Shiffer United States | Reply

Add comment


(Will show your Gravatar icon)

  Country flag

biuquote
  • Comment
  • Preview
Loading



Copyright © 2001-2010 MS Consulting, Inc. All Rights Reserved.