Just tried to build Sharp Architecture through hornget:

horn.exe –install:sharp.architecture

It failed with the message “The type or namespace name 'AutoMap' does not exist in the namespace 'FluentNHibernate' (are you missing an assembly reference?)” and 16 errors with the same message. All I needed to do was to open the SharpArch.sln in c:\users\<my username>\.horn\frameworks\sharp.architecture\working\src\sharparch and Resharper immediately told me to add a using statement to FluentNHibernate.Automapping. Seems like they’ve changed namespace in fluent nhibernate from FluentNHibernate.AutoMap to FluentNHibernate.Automapping. After changing this and made sure that I could compile the solution I just ran the horn command line tool again and it built everything successfully. Just remember to revert the changes or wipe the folder clean so there wont be any conflicts the next time…

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

When using the automapping feature of Fluent NHibernate you may encounter some problems when storing large text data in the database. Below is a class which gets mapped by the automapper in Fluent NHibernate. Both Title and TextContent are strings. The difference between them is that the TextContent property might store a large chunk of text.

image

The default automapper in Fluent NHibernate will create a table with a nvarchar(255) column for both the Title and TextContent. This is fine for most cases but in this case the TextContent property may contain much more than 255 characters. Trying to save the entity with more than 255 characters stored in TextContent will give throw an exception saying:

System.Data.SqlClient.SqlException: String or binary data would be truncated.
The statement has been terminated.

This is the same problem you might run into when using Castle ActiveRecord which also will do a default nvarchar(255) for a string property. It's quite simple to override the default automapper in Fluent NHibernate to change the column in the database into a text type for example. All you need to do is create a class which implements the interface IAutoMappingOverride<T> and add it to the configuration.

   1: public class HeadlineOverride : IAutoMappingOverride<Headline>
   2: {
   3:         public void Override(AutoMap<Headline> mapping)
   4:         {
   5:             mapping.Map(t => t.TextContent).CustomTypeIs("StringClob").CustomSqlTypeIs("text");
   6:         }
   7: }


All you need to do a manual mapping of the field and set the custom type to StringClob and SqlType to text. All the other properties will still be mapped by the automapper in Fluent NHibernate. To make sure that Fluent NHibernate will load the override into the configuration you need to set it up.

   1: return AutoPersistenceModel
   2:        .MapEntitiesFromAssemblyOf<Headline>()
   3:        .Where(t => t.Namespace == "Incendi.Models")
   4:        .UseOverridesFromAssemblyOf<HeadlineOverride>();

On line #4 it tells the automapper to use the overrides from the assembly where HeadlineOverride is declared. If you drop/create the schema with this updated configuration you'll end up with a text type on the TextContent column instead of a varchar(255).

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

In one of my recent projects using ASP.NET MVC (updated to RC2) I was going to use Fluent NHibernate. While using Fluent NHibernate I also needed Castles NHibernate Facility for session management, which would simplify the management of sessions in the repositories in the project. It wasn't as easy as I'd hoped to get it all running smoothly.

EDIT: I’d recommend you to use Sharp Architecture (http://code.google.com/p/sharp-architecture/) which is a project template complete with nhibernate+automap, castle windsor and a bunch of other useful things.

1. Castle binaries

First off, get the latest (trunk) Castle binaries from their build server (or build it yourself). You'll need something later than RC3 (which is the version that's available for download as a release) since the IConfigurationBuilder wasn't public before and there was no way of defining a custom configuration builder which we will leverage to be able to hook into the configuration and making sure that automappings are used.

2. Create custom configuration builder

Based upon this excellent post by Mike Hadlow we're creating a custom configuration builder. This is where the magic from Fluent NHibernate comes into play as well.

   1: public class FluentNHibernateConfigurationBuilder : IConfigurationBuilder
   2: {
   3:     public NHibernate.Cfg.Configuration GetConfiguration(IConfiguration facilityConfiguration)
   4:     {
   5:         var defaultBuilder = new DefaultConfigurationBuilder();
   6:         var configuration = defaultBuilder.GetConfiguration(facilityConfiguration);
   7:         
   8:         configuration.AddAutoMappings(AutoPersistenceModel.MapEntitiesFromAssemblyOf<Headline>());
   9:  
  10:         return configuration;            
  11:     }
  12: }

The method AddAutoMappings() on line 8 does all the magic, it's an extension method from Fluent NHibernate which will wire up the normal automappings from Fluent NHibernate. If you want to use the normal Fluent Nhibernate way with manually mapping entities there's a method called AddMappingsFromAssembly() which you should use instead.

3. Setup HttpModule for Castle NHibernate integration

Since we're using Castle NHibernate facility in a web environment we're going to use their httpmodule for managing sessions as well. If you don't manually set it up correctly you will run into issues like "no session or session was closed" with lazy loading when the session is closed. For example if the view is iterating over a list of objects which are supposed to be lazy loaded. With this HttpModule it will take care of it and setup a session per request.

The <httpModules> section of the web.config looks like this with the addition of the new NHibernateSessionWebModule:

<httpModules>
      <add name="ScriptModule" 
           type="System.Web.Handlers.ScriptModule,
                 System.Web.Extensions,
                 Version=3.5.0.0,
                 Culture=neutral,
                 PublicKeyToken=31BF3856AD364E35"
       />
       <add name="UrlRoutingModule" 
            type="System.Web.Routing.UrlRoutingModule,
                  System.Web.Routing,
                  Version=3.5.0.0,
                  Culture=neutral,
                  PublicKeyToken=31BF3856AD364E35"
       />
       <add name="NHibernateSessionWebModule" 
            type="Castle.Facilities.NHibernateIntegration.Components.SessionWebModule,
                  Castle.Facilities.NHibernateIntegration"
       />
</httpModules>

4. Initialize the container

Do something like this in the Application_Start in your HttpApplication class (usually global.asax.cs). The line number 7 sets the controller factory from the mvccontrib project as the default. This means that the controllers will be resolved by castle windsor and all dependencies will also be resolved from the container.

   1: IWindsorContainer container = new WindsorContainer();
   2:  
   3: // Configure the container either by the ordinary config file with XmlInterpreter
   4: // or by fluent like this etc
   5: container.Register(Component.For<IMyComponent>().ImplementedBy<MyComponent>());
   6:  
   7: ControllerBuilder.Current.SetControllerFactory(new MvcContrib.Castle.WindsorControllerFactory(Container)); 

5. Configure Windsor/NHibernate Facility in web.config

First off we add a new <section> to <configSections> in web.config.

<section
  name="castle"
  type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor" />

The <castle> section  is quite large but we'll break it down.

   1: <castle>
   2:   <facilities>
   3:     <facility id="nhibernate"
   4:               isWeb="true"
   5:               type="Castle.Facilities.NHibernateIntegration.NHibernateFacility,
   6:                     Castle.Facilities.NHibernateIntegration"
   7: configurationBuilder="Incendi.Configuration.FluentNHibernateConfigurationBuilder, Incendi">
   8:         
   9:       <factory id="nhibernate.factory" >
  10:         <settings>
  11:           <item key="show_sql">true</item>
  12:           <item key="connection.provider">NHibernate.Connection.DriverConnectionProvider</item>
  13:           <item key="connection.driver_class">NHibernate.Driver.SqlClientDriver</item>
  14:           <item key="dialect">NHibernate.Dialect.MsSql2005Dialect</item>
  15:           <item key="connection.connection_string">Data Source=.\SQLEXPRESS;Initial Catalog=Incendi;Integrated Security=True</item>
  16:           <item key="proxyfactory.factory_class">NHibernate.ByteCode.LinFu.ProxyFactoryFactory, NHibernate.ByteCode.LinFu</item>
  17:         </settings>
  18:       </factory>
  19:         
  20:     </facility>
  21:   </facilities>
  22:   <components>
  23:     <component id="GenericRepository" type="Incendi.Repositories.Repository`1, Incendi"/>
  24:   </components>
  25: </castle>


On line 4 we tell NHibernate Facility that we'll we using it in a web environment so it can use a special sessionstore for this purpose. Line number 7 indicates that we are specifying a custom configuration builder, which is the one we created in step 2. Make sure the namespace.class, assembly is correct. If you miss this you'll get a not so informative error "classType must be set". Next is the factory where we specify the configuration (if you want some in web.config, in my case I needed the type and connectionstring in the web.config and not specified by Fluent NHibernate since I switch it to SQLite when testing.

Note: I had to add line number 16 after upgrading NHibernate to 2.1

As you can see in the <components> section I've also registered a "GenericRepository" class. This is my base generic repository Repository<T>. There are lots of generic repositories out there, look at Rhino.Commons for example. It's quite easy to write one on your own as well.

6. Using SessionManager from NHibernate Facility in the repository

By setting up NHibernate Facility and retrieving the repository from Windsor which will inject the SessionManager into the Repository. It's now just as easy as calling OpenSession() on SessionManager to get a session. Below is an excerpt from the generic repository I wrote and use in the application to show you how easy it is when you don't need to worry about session management.

   1: public class Repository<T>
   2: {
   3:     private readonly ISessionManager _sessionManager;
   4:  
   5:     public Repository(ISessionManager sessionManager)
   6:     {
   7:         _sessionManager = sessionManager;
   8:     }
   9:  
  10:     public virtual IList<T> GetAll()
  11:     {
  12:         using (var session = SessionManager.OpenSession())
  13:         {
  14:             return session.CreateCriteria(typeof(T)).List<T>();
  15:         }
  16:     }
  17:  
  18:     public virtual T Get(int id)
  19:     {
  20:         using (var session = SessionManager.OpenSession())
  21:         {
  22:             return session.Get<T>(id);
  23:         }
  24:     }
  25: }

 

7. Putting all of it to use with the controllers

For example, I’ve added a UserService component to the castle windsor container which implements IUserservice. The UserController requires a IUserService in the constructor. This dependency will be resolved by castle windsor automatically thanks to the controller factory.

   1: public class UserController : Controller {
   2:     private readonly IUserService _userService;
   3:  
   4:     public UserController(IUserService userService) {
   5:         _userService = userService;
   6:     }
   7: }

Phew, that's a lot of configuration to get it up and running. I hope I didn't forgot anything, drop me a comment if you're having trouble setting it up. Good luck!

Currently rated 1.0 by 2 people

  • Currently 1/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

I started building a web site for my father a few years ago, back then I based it on PHP/MySQL. After some time I discovered Ruby on Rails and rebuilt most of the system using RoR, although I didn't complete the project for a few reasons (not going into detail here). Late 2007 I started to thinking about rebuilding it and leaned toward using .NET. I was thinking I could use it to try out some new technologies in .NET that I hadn't used yet. I'm not a big fan of ASP.NET, so using traditional ASP.NET was out of the question. Since I'm used to PHP and using POST/GET and reading query strings etc I feel that ASP.NET actually confuses developers with postbacks, events and viewstates causing all sorts of problems. Another issue of ASP.NET is the testability, it's cumbersome to write unit tests for ASP.NET applications, it's possible for example using a Model-View-Presenter (MVP) pattern.

Looking for another web framework to use I found Monorail, which is a MVC framework by Castle Project inspired by ActionPack. It's built on top of ASP.NET but, everything gets routed to an action on a controller. I also discovered ASP.NET MVC, however, it was so early that it felt like it changed a lot between every preview, big breaking changes which would meant fixing a lot of code whenever upgrading to a newer preview. That's way I settled with Monorail for the time being.

The web application that was built had the following features

  • Membership (Users, groups and permissions)
  • CMS (pages and menus)
  • Questionnaire
  • Create conference and have members registering to attend
  • Create, send as PDF and manage invoices (the sum of the invoices for the last conference was close to $350 000)
  • Post job advertisements
  • Forum

The web framework used was Monorail and for data access I used NHibernate with ActiveRecord, which made my life so much easier. It's incredible powerful to be able to re-create the database with just a command and be able to switch between different databases by only changing the configuration. At one time I developed the application on my development machine which had a SQL 2005 server and I deployed to a MySQL server and it worked right out of the box. I used the ability to destroy and create the database a lot when creating integration tests. No need to try to reset the database to a specific state, now I was confident that everything was exactly the same each time I ran the tests. The database got swiped and created between each test. There's also the possibility to use an in memory database such as SQLite for performing integration tests, since it only resides in memory it's incredible fast.

I'm pretty pleased with the outcome of the system, it's working great and it's easy to add new features. But, I'm like many of you, I always want to try new things and learn more. Now when ASP.NET MVC has had almost a full year of development since I last visited it I feel like it's time for doing another re-build of the system. This time I'm hoping to be able to re-use some of the business logic and a lot of the data access layer since I'm still going to use NHibernate. I know Entity Framework (EF) has been released, but it's lacking a lot of features and is at the moment inferior to NHibernate. I'm sure it will turn out great when version 2 is released of EF, and I'll probably replace the data access layer when it's out :)

Looking through the code for the web application today trying to look for what needs to be replaced when moving over to ASP.NET MVC from Monorail, it feels like it's not really that much that needs to be changed. I could use a NVelocity view engine keeping the views more or less intact. The data layer is the same and since I wrapped everything in services the controller does not really contain a lot of logic, it'll certainly help. However, obviously there are some core differences between Monorail and ASP.NET MVC. I'm going to go over the issues I encounter one by one as I browse through the code looking for certain perks that needs to either be rewritten in ASP.NET MVC or could just be moved over simply by renaming some classes etc. I'm really looking forward to try out the new features in ASP.NET MVC that I haven't looked at yet, particularly that controller action is not void anymore, instead they return an object. This will make unit testing so much easier.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5