[Screencast] Testen der Anwendungspersistenz – Teil 1

July 8, 2009 at 1:04 PMAndre Loker

Sorry folks, this one is German only!

Ich habe mal meine ersten Schritte in Sachen Screencasts gewagt und präsentiere hiermit meine erste Folge :-)

Die Serie behandelt das Testen der Anwendungspersistenz, d.h. OR-Mappings, Queries usw. am Beispiel von NHibernate. Dieser erste Teil dient als Einleitung und gleichzeitig als Test um sicherzustellen, dass technisch alles korrekt funktioniert. Viel Spaß beim Anschauen. Feedback ist natürlich willkommen!

P.S.: das gelegentliche Zwitschern im Hintergrund sind keine Kompressionsartefakte sondern zwei Wellensittiche…

Posted in: NHibernate | Screencasts | DotNetGerman Bloggers

Tags: , , ,

Patch Producing Pal

June 19, 2009 at 11:47 PMAndre Loker

My contribution to the OSS community for today:

fnh-patches

http://code.google.com/p/fluent-nhibernate/issues/list

Posted in: NHibernate

Tags: , , ,

NHibernate: hiding ID setters

May 27, 2008 at 2:36 PMAndre Loker

Encapsulation is a key concern in object oriented development. Sometimes you have to break encapsulation a bit to make your code interoperable with the infrastructure. In this article I explain how to make a domain entity play well with NHibernate while keeping an encapsulated interface towards the user.

A brief introduction to access methods in NHibernate

Normally I prefer to map fields to database fields rather than properties. This allows me to put logic into the getter and/or setter of the properties if required while persisting the "raw" state of the fields to and from the database. To map fields instead of properties use the access attribute on the respective property element in the mapping file. You can also define the default access method by setting the default-access attribute on the class element. My mapping files generally look like this

   1: <?xml version="1.0" encoding="utf-8" ?>
   2: <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
   3:                    assembly="TheAssembly"
   4:                    namespace="SomeNamespace"
   5:                    default-access="field.camelcase"
   6:                    default-lazy="true">
   7:  
   8:   <class name="TheClass" proxy="ITheClassProxyInterface">
   9:     <id name="ID" access="property">
  10:       <generator class="native"/>
  11:     </id>
  12:  
  13:     <property name="SomeProperty"/>
  14:     <!-- etc -->
  15:   </class>
  16: </hibernate-mapping>

In line 5 I define the default access to be "fields with camel case naming". This means that a property in the mapping file named "SomeProperty" (line 13) will be mapped to a field named someProperty.

You might have noticed that I explicitly set the access strategy to "property" for the ID. This is necessary when you use proxy interfaces. NHibernate needs to be able to access the ID property even if only a proxy is available. If you try to use field access for the ID property you will most likely get an error message like this:

Could not find field 'id' in class 'DessinDB.Process.IDesign'

So we only have to set access to property and everything is cool? Almost.

The dilemma

Let's start with some code:

   1: /// <summary>
   2: /// Proxy interface
   3: /// </summary>
   4: public interface ITestEntity {
   5:   int ID { get; }
   6: }
   7:  
   8: /// <summary>
   9: /// Entity class
  10: /// </summary>
  11: public class TestEntity : ITestEntity {
  12:   private int id;
  13:  
  14:   public int ID {
  15:     get { return id; }
  16:   }
  17: }

And here's the mapping file:

   1: <?xml version="1.0" encoding="utf-8" ?>
   2: <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
   3:                    assembly="NTest"
   4:                    namespace="NHTest"
   5:                    default-access="field.camelcase"
   6:                    default-lazy="true">
   7:  
   8:   <class name="TestEntity" proxy="ITestEntity">
   9:     <id name="ID" access="property" >
  10:       <generator class="native"/>
  11:     </id>
  12:     
  13:   </class>
  14: </hibernate-mapping>

Really simple, still it won't work: NHibernate complains that it cannot find the setter for ID.

Could not find a setter for property 'ID' in class 'NHTest.TestEntity'

Adding a setter to TestEntity.ID is trivial. When we use native ID generation we normally would not want the property to be settable by user code.  As long as we only deal with ITestEnties in our app, this is not problematic. However, NHibernate is still complaining:

Could not find a setter for property 'ID' in class NHTest.ITestEntity'

Adding the setter to the interface is easy, but will also allow any client to set the ID manually - something we do not want.

The solution

I came up with a solution to the problem which is simple, easy to reuse and works without to much "hacking".

First I wrote an interface that provides read/write access to the ID:

   1: /// <summary>
   2: /// Interface for objects that have an id.
   3: /// </summary>
   4: /// <typeparam name="TId">The type of the id.</typeparam>
   5: public interface IIdentified<TId> {
   6:   /// <summary>
   7:   /// Gets or sets the ID.
   8:   /// </summary>
   9:   /// <value>The ID.</value>
  10:   TId ID { get; set; }
  11: }

I then introduced an interface that derives from IIdentified and which hides the setter of its parent:

   1: /// <summary>
   2: /// Interface for domain entities.
   3: /// </summary>
   4: /// <typeparam name="TId">The type of the id.</typeparam>
   5: public interface IEntity<TId> : IIdentified<TId>{
   6:   /// <summary>
   7:   /// Gets the ID.
   8:   /// </summary>
   9:   /// <value>The ID.</value>
  10:   /// <remarks>This property hides <see cref="IIdentified{TId}.ID"/></remarks>
  11:   new TId ID { get; }
  12: }

Now I introduced a convenient abstract base class that implements IEntity<ID> (and indirectly IIdentified<ID>)

   1: public abstract class Entity<TId> :IEntity<TId> {
   2:   private TId id;
   3:   public TId ID { get { return id; }}
   4:  
   5:   TId IIdentified<TId>.ID {
   6:     get { return id; }
   7:     set { id = value; }
   8:   }
   9:  
  10: }

By implementing IIdentified<TId>.ID explicitly I hide the setter from users of IEntity<TId> and Entity<TId>. I can now derive my proxy interface and the entity class from IEntity and Entity:

   1: /// <summary>
   2: /// Proxy interface
   3: /// </summary>
   4: public interface ITestEntity : IEntity<int> {
   5: }
   6:  
   7: /// <summary>
   8: /// Entity class
   9: /// </summary>
  10: public class TestEntity : Entity<int>, ITestEntity {
  11: }

NHibernate is smart enough to detect that IIdentified provides a setter to ID. On the other hand, users of IEntity and Entity will only see the read-only version of ID.

Using ITestEntity:

read-only-id

Using TestEntity:

read-only-id-entity

Of course the setter is available as soon as you cast the entity to an IIdentified<int>:

read-write-id

On the one hand this allows us to inject the ID for example in unit tests. On the other hand it is not very likely that the user will deal with IIdentified<TId> references. So unless the user explicitly converts the entity to an IIdentified<TId> he/she won't see the setter. For my scenarios this is certainly enough.

Posted in: NHibernate | Snippets

Tags: , ,

NHibernate: counting database queries per web request

May 9, 2008 at 4:45 PMAndre Loker

While the upcoming NHibernate 2.0 supports statistics features out of the box, people using NHibernate 1.2 might as well be interested to determine the number of database queries that are executed on the database server.

In my specific case I was just interested in the number of DB queries per web requests, without any additional in-depth analysis. This was mostly meant as an easy detection of SELECT N+1 situations or other obvious bottlenecks. Luckily this can be quite easily done with a neat trick which is based on the fact that NHibernate uses log4net for log output. Ayende Rahien realized that NHibernate writes all executed statements to the NHibernate.SQL logger. So, to get informed over all executed database statements one would only have to implement a custom IAppender implementation and let it listen to the DEBUG messages NHibernate sends to NHibernate.SQL.

Within a few minutes I came up with this appender which counts the number of log messages - i.e. the number of SQL queries - per web request:

   1: using System.Web;
   2: using log4net.Appender;
   3: using log4net.Core;
   4:  
   5: public class CountQueriesAppender : AppenderSkeleton {
   6:     private static readonly object Key = new object();
   7:  
   8:     /// <summary>
   9:     /// Gets the number of database queries that have been executed
  10:     /// during this web request so far.
  11:     /// </summary>
  12:     /// <value>The current query count.</value>
  13:     public static int CurrentQueryCount {
  14:         get {
  15:             var val = HttpContext.Current.Items[Key];
  16:             return val == null ? 0 : (int) val;
  17:         }
  18:     }
  19:  
  20:     protected override void Append(LoggingEvent loggingEvent) {
  21:         var items = HttpContext.Current.Items;
  22:         if (items.Contains(Key)) {
  23:             // increase query count
  24:             items[Key] = 1 + (int) items[Key];
  25:         } else {
  26:             // first query, initialize with 1
  27:             items[Key] = 1;
  28:         }
  29:     }
  30: }

I only need to configure log4net to send the appropriate messages:

   1: <!-- set additivity false to prevent output to other appenders -->
   2: <logger name="NHibernate.SQL" additivity="false">
   3:   <level value="DEBUG" />
   4:   <appender-ref ref="QueryCounter" />
   5: </logger>

That's about it. Now you can access the current query count with CountQueriesAppender.CurrentQueryCount everywhere you like. For example, I render the number of executed queries in the footer of each page in debug mode. Or you could write the count back into a log on end request.

Pay attention though to the moment when you read CurrentQueryCount. Obviously it returns only queries made until that very moment. If you query the value to soon, you might miss some queries.

You can make your appender as sophisticated as you like, of course, e.g. by dissecting the provided log message (i.e. the SQL query) to distinguish between SELECT, UPDATE, INSERT and DELETE queries. Be aware that NHibernate can come up with quite some tricky queries, though, that might not be easy to parse. You might therefore want to leave it at the simple query counter as a rough estimation for now and wait for the release of NHibernate 2.0.

Last but not least: here is an example of how one could use NHibernate 2.0 statistics with MonoRail

Posted in: Databases | NHibernate | Snippets

Tags: , ,