Meeting the needs of your business from a distance

Featured in Visual Studio Magazine Cover Story

by mark shiffer 2. September 2010 16:12

A few weeks ago I participated in a phone interview for an article in Visual Studio Magazine on the Entity Framework. I probably need to work on my vocabulary a bit, but all-in-all I think it came off well. The online version of the article can be found here: Cover Story: Get Ready for the Entity Framework

Tags:

Parallel Programming with Microsoft .NET

by mark shiffer 2. September 2010 15:06

The Patterns and Practices group at Microsoft has released guidance for parallel programming with .NET 4 called Design Patterns for Decomposition and Coordination on Multicore Architectures. The book is available in print and ebook forms from O’Reilly, but the above link is to the free version available via MSDN. Looks like it should be a good, quick read that I’ll need to get to soon.

I have used the Task Parallel Library a bit in .NET 4 now and I am impressed at how it has simplified the syntax for parallel programming. Unfortunately, there is no way to really simplify the concept and thought process necessary for multi-threading an application that requires synchronization.

Tags:

What I Learned This Week: IoC Containers and IDisposable

by mark shiffer 24. August 2010 15:14

I hope to make this a weekly post reflecting on the topics of the week and writing about what came up that was new or that gave me a better understanding of some technology or related topic. We’ll see how long this lasts…

So, I am currently working on an implementation of Entity Framework 4 using WCF and WPF with Prism and, until this week, Unity. I am relatively new to the unit testing bandwagon, and in particular, to dependency injection and inversion of control. I must say, however, that I have quickly become a fan as I have personally witnessed higher quality code with better and more flexible designs being relied upon.

I came across a realization this week how resolving classes with an IoC container that have implemented IDisposable, or worse yet, have dependencies being injected that implement IDisposable somewhere down their dependency chain, can cause headaches. At some point, these disposable instances need to get disposed, but how? They are dependencies to a class instance, but they are not owned by the class instance. Therefore, implementing IDisposable at the top level and disposing of the dependencies that way is out. One could end up disposing a dependency that is shared among other instances. Even if one could implement disposable at the top level, one would still have to keep a reference around at the point of resolution (Resolve call on the container) so that dispose could later be called on it. That can be difficult and/or awkward in some circumstances.

Of course, my first thought, as it often is, is there is no way that I am the first to have come across this problem. Time to Bing it! I was a bit surprised how little people have talked about this particular issue, but there were a few articles out there that mentioned it. I would credit them here, but I don’t recall them at the moment. Most pointed to the fact that Unity is deficient in this area and pointed to Castle Windsor and Autofac as two other IoC containers that make this issue easier to deal with. Both Windsor and Autofac allow one to create scoped sub-containers that track all of the instances that they new-up and later dispose of those instances when the scope is left. For Autofac the code looks like this:

using (var containerScope = SrsIoCContainer.Current.BeginLifetimeScope())
{
    var calculator = containerScope.Resolve<ITimeCalculatorService>();
    return calculator.GetAccumulatedByEmployee(employee, asOfDate);
}

I looked all over Unity for something similar or for a work-around that might accomplish the same thing, but couldn’t find one. The above, from Autofac, solves the issue, and since the IoC container is a pretty small and isolated piece of the software, I have decided to replace Unity with Autofac (still on-going because of Prism’s dependence on Unity for bootstrapping; not as isolated as I had originally thought).

Unfortunately, scoped containers still don’t help when Service Location is brought into the mix. The service locator is setup to use the IoC container as its provider, which works great, but what happens when a service location, which cannot be scoped, new-ups a disposable instance indirectly? I have not come to a full resolution on that yet, other than to avoid service location whenever possible, and, when it is necessary, ensure that the class chain it is resolving will not result in a disposable instance being created by the container.

Tags:

Observal Tracking Library

by mark shiffer 10. August 2010 14:40

Ran across an interesting new library called Observal that uses a fluent coding model to track items in deep hierarchical object models. The following extension methods are currently provided:

Resulting in code that looks like:

public OrgChartViewModel(IEnumerable<Employee> employees)
{
    _rootEmployees = new ObservableCollection<Employee>(employees);
 
    var observer = new Observer();
    observer.Extend(new TraverseExtension()).Follow<Employee>(e => e.DirectReports);
    observer.Extend(new CollectionExpansionExtension());
    observer.Extend(new PropertyChangedExtension()).WhenPropertyChanges<Employee>(x => FilterEmployee(x.Source));
    observer.Extend(new ItemsChangedExtension()).WhenAdded<Employee>(FilterEmployee);
    observer.Add(_rootEmployees);
}

I could see some potential for usefulness here…

Tags:

Reading: Never Eat Alone by Keith Ferrazzi

by mark shiffer 7. August 2010 06:03

So my whole idea of reading one book a month that started a few years back fell apart rather quickly. Not entirely without purpose though. I have slowly gathered a list of blogs that I enjoy reading that help to feed my ADD-like personality with new bits and pieces from various topics that interest me: news, technology, programming, photography, finance, etc… So I now have a list of about 100 blogs that I keep up with and that has taken away from my book reading some. Anyway, enough about that…to the book.

So, I don’t always read tech books. I am also a fan of general business and career related material (thus my MBA). I don’t quite remember how I came across Never Eat Alone, but I believe it was on a top-sellers list at one point or another. Essentially the book bills itself as a how-to for networking and climbing to the top of the business echelons. Keith’s writing style is very informal, often veering into related stories from his life; which makes the book easy to read. The lessons that he gives are all great reminders of simply being a good business-person, but they are far from revolutionary. Essentially the lessons come down to:

1. Always be prepared to meet people and never brush someone off as unimportant because the consequences might not be immediately apparent for your actions.

2. Do your homework and get to know about people you are about to or could meet.

3. Follow-up, enough said.

4. Networking is a two-way arrangement. You have to give a little to get a little.

So that is all well and good, but it’s pretty standard stuff. The really annoying part of the book, which is littered throughout it by the way, is when Keith tells of his random dinner parties and meetings with CEOs of fortune 500 companies and how he “just happened” to meet them and suddenly they were BFFs, as if this were even a remote possibility for the people reading his book. He obviously has clout and has made a name for himself, but I doubt the doors that he opened for himself are a possibility for most.

Keith harps on his “poor” upbringing and how his dad pushed him into networking and started him off on the right path. First, he was no where near poor. His dad put him in private school and used every chance he could to push Keith in front of important people. Keith then went on to Yale and Harvard and from there directly into the high-class of business with Delloite. I have no doubt that Keith worked hard to get where he is today, but his road was well paved for him.

The book ends on a very sour note with a whole chapter devoted toward saying there is no such thing as life balance, essentially work becomes your life. That does not really mesh with my point of view at all, and probably explains why there is no mention of Keith being married or having children. Keith is obsessed with his network and business; fine for him, but I’d rather have a more reasonable and balanced approach to life and work such that I can provide for my family financially and emotionally.

Tags:

Reading

ILMerge Utility

by mark shiffer 30. July 2010 14:13

Ran across ILMerge today from Microsoft Research. It’s been around for a while now, but I’d just never come across it. Essentially ILMerge will fuse.NET assemblies together into a single assembly for distribution.

If one were developing a framework and distributing it to other developers, I could see this utility making the framework easier to use. Beyond that, however, I’m struggling to see any other use for it at this time. Nice to know it is there though.

Tags:

Extending Visual Studio Context Menus

by mark shiffer 19. July 2010 23:29

Just a few quick things that I learned while trying to create a new context menu item on the solution explorer in visual studio:

First, there is a post on how to enable VSIP Logging that comes in handy to figure out the Guids and Ids of the menu items in visual studio. The full post is: Using EnableVSIPLogging to identify menus and commands with VS 2005 + SP1, but this part applies to Visual Studio 2010 as well. Essentially you flip a flag in the registry, restart Visual Studio and then using Ctrl-Shift, Right Click on menu items and a dialog appears with the information that you need. Here is the registry key:
[HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\8.0\General]
"EnableVSIPLogging"=dword:00000001

Second, from an article entitled Dynamic Menu Command in Visual Studio Packages – Part 2, which is where I found the first reference from, it shows  how to define a GuidSymbol, Group and Button appropriately. I am not going to repeat that here. Really it is just repeating what Visual Studio does for you automatically when you create a Package.

Tags:

Fun Coding Challenges

by mark shiffer 16. July 2010 17:03

Pex is an automated unit testing generation tool that Microsoft Research has had out for a while now. Essentially Pex generates various input parameters for your methods helping to find the variations that should be testing to get good code coverage.

The PexForFun website provides an interesting set of code challenges while using Pex to drive it. You are given a starter method that is stripped down to be barely functional and that fails the Pex generated tests. Your goal is to alter the method such that it will pass the tests without any outside knowledge as to what the code is supposed to do and without knowing the Pex unit tests until they fail. It is an interesting approach to advertising what capabilities Pex has and can be a little addicting too.

Tags:

Research | Programming

Development Resources for Any Language!

by mark shiffer 16. July 2010 16:56

Came across a website today called DevCheatSheet that contains a nice compilation of quick references for just about any language (and more) you can think of including: programming, scripting, markup, databases, version control, servers, ORM, blogs, websites, text editors and many other miscellaneous application.

Although fairly comprehensive there are missing pieces. I noticed Team Foundation Server (TFS) was missing from version control and Entity Framework (EF) was missing from ORM. Regardless should be a good place to find a reference for that language that you rarely use and need to remind your self of the syntax for.

Tags:

Programming | Research

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: ,

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