Search This Blog

Showing posts with label NHibernate. Show all posts
Showing posts with label NHibernate. Show all posts

15 September 2010

Avoding hardcoded propertynames in C# .NET

Using strings that denote the name of fields and properties of objects in code are always a bad thing. The reasons are many, its hard to refactor code that contains hardcoded strings with properties names here and there in the code and its easy to make a typo and write some of the property wrong.

Wouldn't it be better if it was possible to avoid this and gather the property from the object directly instead and thereby avoid having to make the typo in the first place?

Luckily this is quite possible with a bit of functionallity added into the project. The below code picks out the name of the property or field of and object and returns the string name for this item. I got this idé from David Morgantini blogpost http://davidmorgantini.blogspot.com/2009/07/nhibernate-disjunction.html

public static string GetFieldName<TObject>(Expression<Func<TObject, Object> exp)
{
     return Regex.Match(exp.ToString(), @"\.(.*)")
               .Groups[1].Value.TrimEnd(new[] { ')' });
}

The code can be used as this

GetFieldName<Book>(b => b.Title)

This will give the string "Title" which can be presumed to be a property of an object named Book.

A more informativ place to use this code is when using NHibernates criteria API which can be cluttered by string constants.

public IList<Book> GetBooksByAuthor(string author)
{
    return Session.CreateCriteria(typeof(Book))
             .Add(Restrictions.Eq("Author", author)
             .List<Book>();
}

Can instead be written as

public IList<Book> GetBooksByAuthor(string author)
{
    return Session.CreateCriteria(typeof(Book))
             .Add(Restrictions.Eq(GetFieldName(b =>
                                              b.Author), author)
             .List<Book>();
}

Hopefully this can help you out with getting more managed code which is easier to maintain in a good state.






15 February 2010

Nhibernate and mapping Enums

When using NHibernate one has to be careful in certain circumstances to avoid small errors that may have a huge impact. In one area an "error" might be hidden for a long time without anybody noticing it and everything working as it should. 

As soon as you create a mapping file with properties that are explicitly given types your should be aware what you are doing. If you for instance create a mapping file where you map a bit column and specify that the type for this column is Int32 and then in the mapping class define this property as an Enum you might be getting into problems. 

Since the class that is used for the mapping in the project might differ from the actual values in the database NHibernate will have problems understanding that nothing really has changed.

For example if you have the following in your mapping file, maybe for mapping up a user and specify gender for the user.
<property name="Gender" not-null="true" type="Int32" />

And the following class defined: 

public class Person
{
     public enum GenderEnum
     {
        Male = 0,
        Female
     }
     public GenderEnum Gender;
}

Once you load this element into memory the property Gender will be tranformed from being an Int32 value in the database to a GenderEnum type in the project. Later on when you either want to unload this object or load another object of the same type or any operation on the object that might trigger an update event for NHibernate such an event will indead be triggered, regardless if you have changed any values or not. The reason for this is that NHibernate detects a change of in the object, the property that is mappped as being Int32 in the database is now returned as an Enum. 

To fix this problem remove the type declaration in the mapping file and let NHibernate resolve the type itself.

A more extensive information about this problem can be found in the following links: