Can’t open a solution? Check your line endings

I’ve run into this issue occasionally over the past few months, but just wrote it off as a minor annoyance.  There are some Visual Studio solutions that wouldn’t open when I’d double-click on them.  Nothing would happen at all.  I’d have to open Visual Studio first, then open the solution from there.  I also noticed that the icon of the file didn’t have the little “10” in the corner:

Bad solution

The issue cropped up again this week, and also happened to a coworker, so I decided to dig into the solution file itself to find out what was wrong.  That’s when I noticed the file had Unix line endings (\n) instead of Windows line endings (\r\n).  Correcting the line endings fixed the file and now the icon looked right:

Good solution

The strange part was other guys in the office had no trouble opening the solution, so why didn’t it work for me?  I figured the “10” in the icon must have something to do with it, and noticed I still had Visual Studio 2008 installed.  I’m guessing this issue happens if you have two versions installed and the file gets opened through the Visual Studio Version Selector.  That can’t seem to handle files with incorrect line endings.

OpenWithVersionSelector

At least this reminded me to finally uninstall Visual Studio 2008.  It makes me a little sad.  That one performed so much better than 2010.

Advertisements

Four years later, a retrospective

Welcome back!  I’ve joined a few of my coworkers in a weekly blog challenge, to write a new post each week.  To start, I figured I should finally write the post I meant to write four years ago, about a small piece of code that saved our rear ends from a huge issue plaguing our production environment. 

Right about this time four years ago, our busy season was just beginning, and we had recently deployed our custom built phone call distributer, Complemax.  We started seeing an issue crop up that was so severe, Complemax effectively stopped routing calls in our call center.  Complemax works by building a grid of phone calls and agents, and scoring each match.  Then the calls are routed to the best matching agents.  After digging through logs, we found that Complemax was processing messages fine, calls were being added and removed as they went on hold or hung up, and employees were updating as they came online or changed their status, but the grid wasn’t being scored! 

So now we had found the root of the problem, but what was the cause?  After analyzing memory dumps, digging through the code, and learning more about low level debugging than I ever had, we finally found the issue was caused by our threading.  The grid makes use of a ReaderWriterLockSlim as its state is updated.  Every five seconds, a read lock would be taken so the current matches could be scored, during which pending updates would wait a short time.  Unfortunately, that lock prioritizes writes over reads, causing our all-important grid calculation thread to be starved by the large amount of updates that were coming in as we received more and more phone calls.

How would we prioritize the read lock, to freeze the grid while we looped through it?  The solution needed to be simple, so we could fix the issue in production as fast as possible.  That’s when I came up with the idea of a “dual” reader-writer lock.  Use two locks on top of each other to give the less common read operation higher priority.  When an update is needed, take a read lock on the first lock and then a write lock on the second lock.  When the grid needs to be frozen, take a write lock on the first lock and pending “reads” on that lock will wait, preventing more updates to the grid.

I’m sure if we had caught the issue before it reached production, we would’ve ended up using something other than a ReaderWriterLockSlim in the first place, but surprisingly in the four years since we added the “dual” lock, we haven’t changed it.  It’s simple, it works, and it handles the load thrown at it.  It was certainly a good learning experience, one I’m glad I had once, but not one I’d ask for.

New Entity Framework designer bugs in SP1 beta

David DeWinter and I have come across a few new and annoying bugs since we installed the Visual Studio Service Pack 1 beta yesterday.  The first and most annoying is detailed in a forum post in the MSDN Entity Framework forum.  The Error List window now lists fake errors for all of our subtypes that are children of abstract entities with a message similar to “Entity types B, C, D are mapped to table A without discriminating conditions on all mappings to the table.”  The project still builds and the errors can be ignored.

Another bug we found today relates to result column bindings for mapped sprocs on subtypes.  We have the results from Insert sprocs mapped to properties on the entity, such the as the Id.  These bindings don’t show up at all in the Mapping Details window, even though they exist in the MSL in the .edmx file.  At first I thought the mapping wasn’t there, and tried to add one.  After deselecting that entity and reselecting it the Mapping Details window showed no result column bindings.  I opened the file in the XML editor and looked at the mapping for that insert sproc.  There were several duplicate result column bindings there from my attempts to add it with the designer.  We’ve reported this bug at Microsoft Connect.

The last problem we ran into is not actually a bug, but a change in behavior.  Dave created a thread about it at the Entity Framework forum.  We had created the following extension method relying on the EntityKey of an EntityReference:

        /// <summary>

        /// Loads the specified <see cref=”EntityReference”/> if it is not loaded

        /// and only if there is an actual reference to load.

        /// </summary>

        /// <param name=”entityReference”>The entity reference </param>

        public static void LoadIfNeeded(this EntityReference entityReference)

        {

            // The EntityKey will be null if there is no reference.

            if (!entityReference.IsLoaded && entityReference.EntityKey != null)

            {

                entityReference.Load();

            }

        }

We had a situation where an entity shares a 0..1 relationship with another entity.  Calling Load() when that relationship was null caused an unnecessary database hit, which was exaggerated when called in a loop on several entities.  We’ve since been able to remove the need for a LoadIfNeeded() method, but it is still nice to have an EntityKey on references for other uses.

We’ll likely run into a few more caveats with the new beta, but the fixes to previous bugs are always welcome.  Hopefully it won’t be too long of a wait before another release.  One thing that surprised me was how long it took to install the service pack, much longer than the install of the .NET Framework 3.5 SP1 beta.