Updated version of Monitored Undo Framework released


Today I released an updated version of the Monitored Undo Framework.

Changes include:

  1. A new parameter on the DefaultChangeFactory's methods for specifying the "description of the change". This can be helpful in cases where the UI shows a list of the undo / redo changes.
  2. A new WPF sample that shows, in a simpler codebase, how to use the framework.
  3. Updated build script that compiles all solutions, run the tests, and package the NuGet package.

These changes are also available via NuGet.

Cheers!

author: Nathan Allen-Wagner | posted @ Tuesday, January 31, 2012 10:24 AM | Feedback (0)

"tfpt unshelve /migrate" Doesn't Account for Renames


A quick note about Team Foundation Power Tools (TFPT)'s "Unshelve" command…

tfpt unshelve has a /MIGRATE switch that will allow unshelving changes into a different branch / location than the one where they were originally shelved. I won't re-iterate the many articles describing how to use this command.

One issue that I ran into is unshelving a set of changes into a branch where some of the shelved files had been renamed / moved. It seems that the /migrate switch doesn't go back into TFS version history to locate the renames. Instead, it simply pulls out the changes and re-applies them to the new location.

For Example:

Let's say that I start with Branch A. One user (John Doe) get's latest and starts making changes.

Branch A
    Src
        File1.txt

Then… a different user (Jane Smith) renames File1.txt and checks that in.

Branch A
    Src
        File1_RENAMED.txt

Then… (for some reason), they need to move John's changes from Branch A to another branch. (Let's pretend that Branch A is the main branch, but the changes are too large for this iteration, so they want to move them to a separate branch for a future release.) So they create Branch B, which looks like this:

Branch B
    Src
        File1_RENAMED.txt

Then… John shelves his changes and they attempt to use tfpt unshelve /migrate to move the changes to Branch B.

But a strange thing happens. They end up with this:

Branch B
    Src
        File1.txt
        File1_RENAMED.txt

Huh? How'd that happen?

Someone who knows version control well could probably explain why, and suggest that this is obvious. But it wasn't to me, and as a result, some of the changes in the shelveset did not make it into the target solution.

How I should have done it…

If I was going to do this again, I think I'd:

  1. Get the source and the target branches to the same version. (Merge changes as needed between the branches.)
  2. In the source branch, get latest version so that the local workspace has the latest version.
    1. This should propagate any pending renames / moves that were made in that source branch, or it's parent branches.
  3. Shelve the changes that should be moved.
  4. In the target branch, get latest version.
  5. Run tfpt unshelve /migrate …

 

Cheers!

author: Nathan Allen-Wagner | posted @ Thursday, January 26, 2012 4:14 PM | Feedback (0)

A Visual Studio Extesion to make Scrolling Better!


Hi All,

A friend of mine (John Nastase) saw a tweet or two of mine complaining about scrolling in Visual Studio.

What did he do? He wrote a VS extension to make it happen!!!

Here's the extension that he just published in the VS extension gallery.

It basically adds a "cursor buffer" space to the top and bottom of the window so that as arrow down the page, the page starts to scrolling before the cursor hits the VERY BOTTOM OF THE PAGE. Instead, it starts scrolling a little earlier so that you can see what's coming. This saves you from scrolling too far and then having to arrow back up to where you want to be.

Brilliant!

Cheers!

author: Nathan Allen-Wagner | posted @ Monday, January 23, 2012 10:37 PM | Feedback (0)

EF Inserts Failing Because of Missing Association in SSDL


I just found that Entity Framework (4.0) can stumble on One-To-One relationships if the EDMX's schema storage layer (SSDL) is missing the association that represents the Foreign Key in the database. I suppose this makes sense, but it's only obvious to me in hindsight.

I don't know how my EDMX ended up missing the SSDL association for the Foreign Key, but it was missing. However the the Conceptual Layer had the relationship, so the diagram made it look like it was associated. And because this is a supported scenario, it didn't complain at me that I was missing anything.

But…

When I went to save the records, EF stumbled on the insert. In my case, I had two entities that were related by a "1 to 0..1" relationship. I'm guessing that EF saw this, evaluated the SSDL layer's metadata and decided that order of insert didn't matter. As a result, it inserted them in alphabetical order… and failed. It failed because in my DB, I did have a foreign key.

The fix was to manually add the association into the SSDL layer.

Note: Editing EDMX files by hand SUCKS!

author: Nathan Allen-Wagner | posted @ Thursday, January 19, 2012 4:37 PM | Feedback (0)

Microsoft's MVP program and Rob Eisenberg


This is a long read, but it's got some detailed insight on the MVP program at Microsoft. I've heard these sentiments before, and I'm sure that it's not black and white. Regardless, Microsoft's actions in this case are unacceptable.

http://devlicio.us/blogs/rob_eisenberg/archive/2012/01/04/how-i-lost-regained-and-then-turned-down-an-mvp-award.aspx

If you don't know Rob Eisenberg, he's the creator of Caliburn and Caliburn Micro frameworks for XAML based platforms (WPF, Silverlight, WP7). If you want to have your mind blown, take a look at his source code for Caliburn Micro (and even more so for Caliburn). While you're at it, watch his "Build your own MVVM framework" presentation. I reviewed a lot of WPF frameworks, but Caliburn Micro stands alone in it's elegance, simplicity, and amazing use of the C# / .NET platform.

I seriously hope that MS addresses whatever is behind this story. We need people like Rob! They should be rewarded for their amazing contributions to the community.

author: Nathan Allen-Wagner | posted @ Thursday, January 05, 2012 2:34 PM | Feedback (0)

Good Times at the .NET SIG…


Had a great time at the .NET SIG last night where we talked about Software Craftsmanship and did Katas together. We had a good turn out (~40 attendees), and we spent a majority of the time doing Katas.

I was quite impressed by the group's willingness to try Pair Programming. Here's pic that Andrew Thorne snapped of one side of the room. You can see people working on a kata, mostly in pairs!

image

https://twitter.com/#!/Bennett_Adelson/status/146744206772281345/photo/1/large

 

Thanks to those of you who came out. Hope you enjoyed the time and got something out of it.

Cheers!

author: Nathan Allen-Wagner | posted @ Wednesday, December 14, 2011 8:15 AM | Feedback (0)

Signing EXEs and MSIs with Signtool via TFS Builds


I won't repeat the "Signing your code with Signtool" walkthrough that is already detailed in 50,000 other posts. You can Bing that with Google as easily as I did. What I will share is a little issue that tripped me up for a bit.

I wanted the code signed as part of the TFS automated build. And, while I could run the command line myself, I could not get it to work under TFS builds.

The Scenario

  • I wanted the keys in the certificate store, rather than on disk. This makes it possible to use the certificate without storing the certificate's private key password on disk.
  • The build process is NOT running as local admin.
  • The code signing tasks happen as a "Post-Build" event, specified in the project's properties.
  • The certificate was installed in the Machine Store, not a specific account's store.

The Problem

I could run the Signtool command under my account and it worked. But if I ran under a limited account, it didn't work.

I tried copying the cert into the service account's personal store, but that didn't help.

The Solution - Permissions, of course!

It wasn't immediately obvious because of various error messages such as:

  • "No certificates were found that met all the given criteria"
  • "No provider was specified for the store or object"
  • … and others

I figured that I'd check to see what Signtool was looking for to see if I could isolate the issue. ProcessMonitor did the trick in a matter of minutes. Spinning it up, I found that it was getting access denied on the Machine Store's key files. I've seen this before related to IIS / ASP.NET (I think).

On Windows Server 2003 and earlier, the machine keys are stored under:
C:\Documents and Settings\All Users\Application Data\Microsoft\Crypto\RSA\MachineKeys

On Windows Server 2008, these are now under:
C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys

I found the file related to the cert that I just installed and inspected permissions. Just "Administrators" and "System". I granted my build service account read access and, VOILA, the Signtool works!

If anyone knows how to manage cert permissions without mucking with the file system directly, please do tell! And if you know why this is the way it is, I'd love to hear it.

Cheers!

author: Nathan Allen-Wagner | posted @ Friday, November 18, 2011 3:23 PM | Feedback (0)

LINQ to Excel = Bliss!


It's fun when an API is so awesome that it just makes you smile uncontrollably. That's how I felt after using Linq To Excel!

http://code.google.com/p/linqtoexcel/

I dreaded the thought of coding against Excel and decided to search around for the best approach. StackOverflow served up a couple options, including LINQ to Excel. Now I like LINQ, so it naturally attracted my eye. The project is completely awesome! It let me extract data from multiple sheets in an excel workbook with just a few lines of code, and no direct dependency on Excel to be installed on the machine!

Awesome!

So, if you need to pull data out of Excel, look no further. You can even pull the package into your project via NuGet!

Cheers!

author: Nathan Allen-Wagner | posted @ Tuesday, November 08, 2011 11:28 PM | Feedback (0)

Poor-man's .NET Linker = Embed Your Dlls


I had a need to create a simple .NET app, but it needed to be self contained in a single EXE. Native developers (C / C++) can easily create single EXE programs by utilizing the linker to pull the various pieces into the EXE. Not so easy for .NET.

I remembered reading about options for this in the past, and decided to take the quick & easy route. Options that I've heard of include:

  • Use the Mono tooling to "link" the dlls into the exe
  • Hook "type-resolution" events and locate the types in DLL embedded resources (no need to put dlls on disk)
  • Use embedded DLLs and simply copy them to the current directory on startup

Quick and easy for me is the last option. I embedded the DLL in the EXE and then extracted it to the file system on app startup.

One catch…

NET's type resolution seems to work on a class by class basis. .NET wants to resolve all dependencies of the class, even if you have not yet instantiated the referenced type. So… Move the logic that uses the referenced type into a separate class. Make sure to extract dlls from the EXE before creating an instance of that class and you should be good to go.

author: Nathan Allen-Wagner | posted @ Thursday, November 03, 2011 3:17 PM | Feedback (0)

Don't Reuse Context with Entity Framework Self Tracking Entities


With EF Self Tracking Entities, it appears that using a single context for a "read" and then a subsequent "save" does not work. I guess I could let this one go as "By Design", but that doesn't mean I have to like it…

The Scenario: EF Self Tracking Entities for an MVC 3 site

I have an MVC3 site wherein I'm using Self Tracking Entities. These are exposed by repositories that I'm injecting into the controllers via Ninject. Since we're letting our IoC container create these items, the lifetime of the instances are "per request".

Inside the repository, I create an instance of the EF context in the constructor and use it for the lifetime of the instance. I know that it's bad form to hold on to an EF context for a long time, but a single request isn't all that long. Should be ok.

The Problem: Deletes don't work

My team started writing pages and stumbled on a problem. Deletes don't work!

I quickly assumed that this was the classic misunderstanding that Remove() != MarkAsDeleted(). Once we got past that stumbling block, we found that deletes still didn't work.

Digging In….

So I dug into the code, setup more unit tests to exercise the repositories. Definitely not working, in spite of the fact that I have nearly identical code in another application.

… Hours pass

… And I finally located the issue after much digging and searching.

If I re-use the same context for the "read" and the subsequent "save", then things don't work quite right. The changes to a given entity are detected, but deletes are not.

However, if I use a separate, newly created context for the save, then things do work. How come?

Digging into the STE template a bit further, we find that its ApplyChanges() method only analyzes the supplied object hierarchy for instances that don't already exist in the current EF context. If the EF context already knows about the instance, then ApplyChanges() doesn't analyze it's ObjectChangeTracker for changes. However if the object is not already tracked by the context, then the STE code will inspect the ObjectChangeTracker for changes and update the context accordingly.

That's a problem. I fetch an instance and it's children. Then I delete a child instance out of the collection. This sets the deleted instance's state to "deleted" and registers it in the parent's ObjectChangeTracker as an "item removed from a collection". Now, I call ApplyChanges(), but it says… "yeah, I already know about that entity. I don't need to check for changes."

Solution #1 - Always create a new EF Context

Set up the repositories to create a new context for each method call. I'm still considering this option, and may update the repository to do so, but I feel like this is a work around, not a fix.

Solution #2 - Alter the Self Tracking Entities T4 Template

While solution #1 would work, I kinda feel that STE's context should be able to support read -> change -> save on the same context. Why should I create another context? The objects are already in memory, tracked by EF.

So I looked into altering the EF STE T4 template to analyze "added" as well as "existing" entities when calling ApplyChanges(). Turns out it wasn't too bad:

Essentially, the above code gets the union of the entities already in the context, plus entities supplied to ApplyChanges(). Then it analyzes this complete set of entities for changes.

My unit tests against the modified ApplyChanges() implementation showed that it handled the "Read -> Change -> Save" sequence against a single instance of the EF context. I haven't tested this down every possible path, but so far it seems solid. And if you don't like this approach, then just go back to solution #1.

Side Note - Why am I using STE in the first place?

You may ask, "If you want to "read -> change -> save" all on the same context, why use STE in the first place? Good question!

Personally, I like the capabilities of entities generated by the STE template. The entities themselves are basically POCOs, but have the necessary logic in place to keep the hierarchy in tact and consistent. Since they're POCOs, I don't need any EF stuff anywhere outside my repository.

And while some of the logic in the application does "read -> change -> save" on the same context, there are other cases where I do work with them detached from the context.

 

Cheers!

author: Nathan Allen-Wagner | posted @ Tuesday, November 01, 2011 1:27 PM | Feedback (0)