Saturday, October 22, 2011

FluentConfigurationException: Pitfalls of Auto-Completion

Working on some code I ran into a FluentConfigurationException when trying create the session factory. With (much) more experience I probably would have been able to resolve it much faster. I’d like to share my findings with you. Maybe it’ll help you saving time.

The usual message I got was: “An invalid or incomplete configuration was used while creating a SessionFactory. Check PotentialReasons collection, and InnerException for more detail.” I followed the advice and checked the PotentialReasons collection. It had a count of 0. In other words it was empty.

Next I checked the inner exception and it was of the same type FluentConfigurationException and the message was the same. Again the PotentialReasons collections was empty. However, there was an exception inside of the inner exception. This was of the type System.InvalidOperationException. The message was: “Unsupported mapping type 'DataAccessTest.Job'”. Searching the internet didn’t yield much of an answer.

I tried a lot of different things and created even a new project. In the end I found that I was a victim of autocomplete. Here is the offending code:

public class JobMap : ClassMap<JobMap> {
   public JobMap() {
      Id(x => x.Id());

As I typed Job to provide the type parameter to the generic base class ClassMap<T> the autocomplete feature turned it into JobMap. Since this was just a test all I wanted to map was just the Id. Had I mapped other members I would have noticed that the line where it maps the id is incorrect as well. Have a look at the class that I wanted to map:

public class Job {
   public virtual Guid Id { get; private set; }

You will notice that the member ‘Id’ is a property and not a method. In the mapping class above the lambda expression ‘x => x.Id()’ tries to map a method ‘Id()’. The base class ClassMap<T> obviously has a method ‘Id()’ so was happily inserted by auto-completion as well. Had I mapped additional Job properties in the JobMap class I would have noticed that something was wrong. This way however, I learned that although auto-completion has made me much more productive there are times when it pays off to be very careful about what it does.

To complete this post here is the correct code for the mapping:

public class JobMap : ClassMap<Job> {
   public JobMap() {
      Id(x => x.Id);

Notice the correct class name (‘Job’) as type parameter for the generic based class ClassMap<T> and also the correct lambda expression now mapping a property rather than a method.

Monday, October 17, 2011

Strong Name Utility Message: "x.dll does not represent a strongly named assembly"

We are in the process of migrating our code base from Visual Studio 2008 to Visual Studio 2010. To give you an indication for the size of the effort: Our product consists of multiple solutions most of them being pure C#. One of the solutions, however, contains about 70 projects most of which are C++ with a mix of both managed and unmanaged C++. Some of these projects were originally created in the 90s and upgraded multiple times to Visual Studio 2008. We are talking about over 1 million lines of C++ code.
To prepare for the actual upgrade we have a code branch separate to trunk. In this separate branch we run test upgrades on a regular basis. For a successful upgrade we need to eliminate all build errors that are reported after the migration. In addition to this we also endeavor to resolve all warnings although we are aware that we may not be able to resolve them completely.
Today I came across this warning/error message today in Visual Studio 2010 SP1 (Service Pack 1). While building I ran into a bug that was reported for Visual Studio 2010 and that was supposed to be fixed in SP1. Signing a C++/CLI assembly in VS 2008 worked but is broken in VS2010. A work around has been provided for both VS2010 and VS2010 SP1.
When I used this work around it worked like a charm for one project but failed for the next project. In my view this indicated that there had to be at least one other factor that influences the outcome.
I used a diff tool to compare both project files (*.vcxproj) to see differences in the compiler and linker options but also to eliminate these differences one at a time. In my particular case I found that I was able to resolve the problem by removing the ‘/clr’ from the project settings and instead applying ‘/clr’ to each file source file (*.cpp) that requires individually.
Update: It some cases switching off incremental linking seems to help.
(Disclaimer: This solution may not work in all cases.)