Jul 232014
 

The following methods are handy for getting the sql from NH queiries in the c# code:

// Use this for QueryOver
public String GetGeneratedSql(IQueryOver queryOver)
{
   return GetGeneratedSql(queryOver.UnderlyingCriteria);
}

public String GetGeneratedSql(ICriteria criteria)
{
   var formatter = new BasicFormatter();
   var criteriaImpl = (CriteriaImpl)criteria;
   var sessionImpl = (StatelessSessionImpl)criteriaImpl.Session;
   var factory = (SessionFactoryImpl)sessionImpl.Factory;
   var implementors = factory.GetImplementors(criteriaImpl.EntityOrClassName);
   var loader = new   
         CriteriaLoader((IOuterJoinLoadable)factory.GetEntityPersister(implementors[0]), 
                     factory, criteriaImpl, implementors[0], sessionImpl.EnabledFilters);

    return formatter.Format(loader.SqlString.ToString());
}

// Use this for Linq
private static void ShowSql(IQueryable queryable, IStatelessSession session)
{
   var formatter = new BasicFormatter();
   var sessionImp = (ISessionImplementor)session;
   var nhLinqExpression = new NhLinqExpression(queryable.Expression, sessionImp.Factory);
   var translatorFactory = new ASTQueryTranslatorFactory();
   var translators = translatorFactory.CreateQueryTranslators(nhLinqExpression.Key,    
                         nhLinqExpression, null, false, sessionImp.EnabledFilters, 
                         sessionImp.Factory);

    var sql = formatter.Format(translators[0].SQLString);
}

 

 Posted by at 9:19 am
Jun 262013
 

Here are some things that I try to bare in mind when writing unit tests. Most of these (if not all) can be found in the “Pillars of good tests” chapter of the Art of  Unit Testing Boook:

  • Test one thing in each test. E.g. testing the return value and several interactions in one test is not good and is brittle.
  • Test the behaviour of a class/method not the internal flow through that method
  • DRY! do not cut and paste code, use helper methods to get code reuse in the same way that you would in prod code. Make sure the helper methods are simple and are named in a way that aids code readability.
  • Keep tests simple  and not too lengthy.
  • Test only the core aspect of each test, do not test side effects, e.g. A test may checking the return value of a method, but you may feel that while you are there you may as well check that one of the dependencies is not called. Don’t do this!! If at a later point the dependency is removed all of you tests will break, rather than the one or two that specifically test this interaction.
  • Use stubs rather not mocks and keep the interaction definitions as loose as possible (but no looser).
  • If you find that your tests are complex re factor your code to make it easier to test!
  • Avoid doing too much in the Test Setup (if indeed anything at all…). You can nearly always use a helper method to achieve the same effect as a class variable and it is more explicit. For example:

Don’t do this:

[TestClass]
public class MyTestClass
{
   private IMyInterface myDependency;

   [TestInitialize]
   public void Setup()
   {
      myDependency = MockRepository.GenerateStub<IMyInterface>();
      myDependency.Stub(x => x.SomeMethod(2)).Return(6);
   }

   [TestMethod]
   public void MyTest()
   {
      // Arrange
      var objectToTest = new MyClass(myDependency);

      // Act
      var result = objectToTest.DoSomethingWith(2);

      // Assert
      Assert.AreEqual(6, result);
   }
}

Do this:

[TestClass]
public class MyTestClass
{
   [TestMethod]
   public void MyTest()
   {
      // Arrange
      var objectToTest = new MyClass(StubDependencyWith(2, 6));

      // Act
      var result = objectToTest.DoSomethingWith(2);

      // Assert
      Assert.AreEqual(6, result);
    }

    private IMyInterface StubDependencyWith(int input, int output)
    {
      var myDependency = MockRepository.GenerateStub<IMyInterface>();
      myDependency.Stub(x => x.SomeMethod(2)).Return(6);
      return myDependency;
    }
}
 Posted by at 12:36 pm
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