Jan 152013
 

I use Heart Internet for my hosting both Linux and Windows. I recently tried to upgrade and existing MVC 2 app to MVC 3 and ran into all sorts of problems. No matter what I did I was greeted with the: “403 – Forbidden: Access is denied.” message.

I logged a support ticket with Heart and I have to say that they were very quick to respond. It turns out that you need to add the following to your web.config:

<system.webServer>
<validation validateIntegratedModeConfiguration="false"/>
<modules runAllManagedModulesForAllRequests="true" />
</system.webServer>

Following on from the above my esteemed colleague Alex (Frazer from Dad’s army) pointed me at the following article:

Don’t use runAllManagedModulesForAllRequests=”true” when getting your MVC routing to work

I have yet to try this, but it sounds reasonable…

 Posted by at 11:37 am
Aug 072012
 

Following on from my post on NH testing using SQL CE. Here is an even better suggestion from Ayende himself. This article shows how to use SQLite for unit tests. This is a better option than using SQL CE IMHO as you don’t even require a db file. Here’s the article:

NH Unit Testing with SQLite

 Posted by at 1:51 pm
Jul 232012
 

One of our team ran into some issues with NH and Varchar(Max) this week. The gist of the problem is outlined in his own words:

Beware that when mapping to a NVARCHAR(MAX) column in NHibernate, the default mapping will map to a fixed-length string of 8000 characters for ANSI and 4000 characters for Unicode strings. Obviously any strings longer than this will be truncated when stored in the database.

To fix this, it is necessary to use a “custom type” mapping in the NHibernate configuration. Example below using FluentNHibernate;

Map(x => x.Notes).CustomType("StringClob")

Further discussion of this gotcha can be found on this blog and on stackoverflow.

 Posted by at 7:42 am
Jul 232012
 

When you use NHibernate to eagerly load a complex domain model you often end up with a large amount of data being returned to populate various child collections (a Cartesian product of all the child collections). In this situation it is often better to break the query up into several parts and let NH glue the domain model together.

The following article discusses this:

NHibernate Avoiding Unnecessary Cartesian Products

 Posted by at 7:37 am
Jun 122012
 

The following TSQL snippet identifies all foreign keys in the database that reference a give table:

DECLARE @tableName sysname

SET @tableName = 'Person' -- Your table name goes here

SELECT f.name AS ForeignKey,
OBJECT_NAME(f.parent_object_id) AS TableName,
COL_NAME(fc.parent_object_id,
fc.parent_column_id) AS ColumnName,
OBJECT_NAME (f.referenced_object_id) AS ReferenceTableName,
COL_NAME(fc.referenced_object_id,
fc.referenced_column_id) AS ReferenceColumnName
FROM sys.foreign_keys AS f INNER JOIN sys.foreign_key_columns AS fc ON f.OBJECT_ID = fc.constraint_object_id
WHERE OBJECT_NAME (f.referenced_object_id) = @tableName
 Posted by at 9:54 am
May 312012
 

Here’s a quick post to show how to execute a Grouping query using NHibernate 3.2+ and QueryOver. Its actually pretty easy, but it took me a few minutes to work out.

So If I have a Person object as follows:

   public class Person
   {
      public Id { get; set; }
      public string EyeColour { get; set; }
      public int Age { get; set; }
   }

If I want to group the people by EyeColour and Age, I simply do the following:

   Person personAlias = null;
   var transformer = new AliasToBeanResultTransformer(typeof(Person));

   var results = session.QueryOver<Person>()
                    .SelectList( list =>
                        list
                           .SelectGroup(x => x.EyeColour).WithAlias(() => personAlias.EyeColour)
                           .SelectGroup(x => x.Age).WithAlias(() => personAlias.Age)
                           .SelectMin(x => x.Id).WithAlias(() => personAlias.Id)
                    )
                    .TransformUsing(transformer)
                    .List<Person>();

Note the use of the Alias and the transformer. This allows us to transform the results back into a Person object. You can however use a completely different result object if you want…

 Posted by at 12:22 pm
May 292012
 

After a couple of months off Mapping By code, I have been using it again for a small project that I am working on. I found my previous blog posts a useful reminder, but realised that I hadn’t added any sample code for building a session factory.

So here is is, a sample Session factory builder using NH 3.3 and Mapping by Code:

    public class SessionFactoryBuilder
    {
        public static ISessionFactory BuildSessionFactory()
        {
            var nhConfiguration = ConfigureNHibernate();
            var mapping = GetMappings();
            nhConfiguration.AddDeserializedMapping(mapping, "PUT MAPPING NAME HERE");
            return nhConfiguration.BuildSessionFactory();
        }

        private static Configuration ConfigureNHibernate()
        {
            var configure = new Configuration();
            configure.SessionFactoryName("BuildIt");

            configure.DataBaseIntegration(db =>
            {
                db.Dialect<MsSql2008Dialect>();
                db.Driver<SqlClientDriver>();
                db.KeywordsAutoImport = Hbm2DDLKeyWords.AutoQuote;
                db.IsolationLevel = IsolationLevel.ReadCommitted;
                db.ConnectionString = ConfigurationManager.ConnectionStrings["CONNECTION_STRING_KEY"].ConnectionString;
                db.Timeout = 10;

                // enabled for testing
                //db.LogFormatedSql = true;
                db.LogSqlInConsole = true;
                //db.AutoCommentSql = true;
            });

            return configure;
        }

        protected static HbmMapping GetMappings()
        {
            //There is a dynamic way to do this, but for simplicity I chose to hard code
            var mapper = new ModelMapper();

            mapper.AddMapping<PersonMap>();
            var mapping = mapper.CompileMappingFor(new[] { typeof(Person) });
            return mapping;
        }

    }

Inferred Mappings

If you simply want to point the ModelMapper at an assembly and let it work out which mapping classes to include, you can use the following syntax:

   mapper.AddMappings(Assembly.GetAssembly(typeof(AssetIdentifierMap)).GetExportedTypes());
   var mapping = mapper.CompileMappingForAllExplicitlyAddedEntities();

Conventions

I tend to tread lightly with conventions, but here are a couple that I use regularly:

class – Id Convention

Map the Id property of the class to a column with the name ClassType + “Id” and use an Identity Generator for new id vals.

   mapper.BeforeMapClass += (mi, t, map) => map.Id(
           x =>
           {
              x.Column(t.Name + "Id");
              x.Generator(Generators.Identity);
            });

In the above a class Person with a Id property would have the Id property mapped to a column called “PersonId”.

Many To One Convention

Maps many to one properties (i.e. foreign key columns) to a column with the name “RelatedClassType” + Id

   mapper.BeforeMapManyToOne += (modelInspector, propertyPath, map) =>
      map.Column(propertyPath.LocalMember.GetPropertyOrFieldType().Name + "Id");
 Posted by at 7:30 am
Mar 062012
 

Most of NHibernate’s value is in its ability to manage a domain model and seamlessly send changes to the database. However, it can be used for Readonly and ETL scenarios (caveat: there may be better alternatives for these use cases).

If you decide you would like to use NH in this way then I recommend using a Stateles session as it performs better and in the Readonly use case it will not save chanegs to the database without an explicit call to the Insert or update methods.

A stateless session is very similar to a normal session and is used in the following way:

using (var session= sessionFactory.OpenStatelessSession())
using (var transaction = statelessSession.BeginTransaction())
{
    // Select like this as normal
    var richard = session.QueryOver().
                     Where(p => p.Name = "Richard").SingleOrDefault();
    richard.Address1 = "1 A New Road";

    var paul= new Person{ Name = "Paul", Nickname = "Mad Dog" };

    session.Insert(paul);
    transaction.Commit();
}

The net effect of the above is that “Paul” (aka Mad Dog) will be added to the database, but the changes to “Richard” will not. This is because Stateless sessions do not use the 1st Level cache and therefore do not track changes to objects.

For more info, see:

Bulk Data Operations With the Sateless Session

Stateless Session Pitfalls

 Posted by at 4:27 pm