Fluent NHibernate – mapping one to one relation

Posted by – March 7, 2012

Few weeks ago I’ve started new project based on ASP.NET MVC, jQuery and NHibernate. It has some part of functionality inspired by ELMAH but mainly goes in a different direction addressing some additional scenarios and it is called WebConsole. It is able to catch exceptions from ASP.NET application and save them with whole context in centralized database. It can also log every request and response even if there was no exception. As you can see everything is spinning around HTTP request and response model.

In order to store information about HTTP communication I had to create NHibernate entities and map them to a database. After some short brainstorming I came up with three basic entities:

Activity – representing single “act” of communication between a client and a server

public class Activity : Entity
{
    // ... some properties and methods removed for readability

    public virtual int Id { get; set; }

    private Request _request;
    public virtual Request Request
    {
        get { return _request; }
    }

    public virtual void Add(Request request)
    {
        if (_request != null)
        {
            _request.Activity = null;
        }
        _request = request;
        _request.Activity = this;
    }

    private Response _response;
    public virtual Response Response
    {
        get { return _response; }
    }

    public virtual void Add(Response response)
    {
        if (_response != null)
        {
            _response.Activity = null;
        }
        _response = response;
        _response.Activity = this;
    }
}

Request – representing request made by the client

public class Request : Entity
{
    // ... some properties  and methods removed for readability

    public virtual int Id { get; set; }

    public virtual Activity Activity { get; set; }
}

Response – representing response from the server

public class Response : Entity
{
    // ... some properties  and methods removed for readability

    public virtual int Id { get; set; }

    public virtual Activity Activity { get; set; }
}

During one Activity there can be no more than one Request and Response. With this assumptions in mind I’ve started thinking how to map these relations using Fluent NHibernate. It was obvious for me that this are one to one relations, but turned out it is not so obvious how to map them. After some googling, playing with the code and a cup coffee I found right configuration which work nice.

From the Activity side relations has been mapped in a standard way by using HasOne method with some other modifiers for the access and lazy loading. One thing worth mention is Id mapping with automatically generated values.

public sealed class ActivityMap : ClassMap
{
    public ActivityMap()
    {
        // ... some mappings removed for readability

        Id(x => x.Id);

        HasOne(x => x.Request).Access.CamelCaseField(Prefix.Underscore)
                .Cascade.All().LazyLoad();

        HasOne(x => x.Response).Access.CamelCaseField(Prefix.Underscore)
                .Cascade.All().LazyLoad();
    }
}

From the Request and the Response mapping side thing looks quite different. This is because I had to “tell” that Id should not be automatically generated but taken from the Activity. Additionally HasOne relation looks different because it has to act as a foreign key and be constrained to values of the Activitie’s identifier (Id).

public sealed class RequestMap : ClassMap
{
    public RequestMap()
    {
        // ... some mappings removed for readability

        Id(x => x.Id).GeneratedBy.Foreign("Activity");

        HasOne(x => x.Activity).Constrained().ForeignKey();
    }
}

public sealed class ResponseMap : ClassMap
{
    public ResponseMap()
    {
        // ... some mappings removed for readability

        Id(x => x.Id).GeneratedBy.Foreign("Activity");

        HasOne(x => x.Activity).Constrained().ForeignKey();
    }
}

At the end we came up with a solution where the main entity is responsible for generating identifiers and all other entities in one to one relation use them as theirs primary and foreign keys.

Hey, keep in touch!! Follow me on Twitter, @marcinobel or subscribe to this blog.
3 Comments on Fluent NHibernate – mapping one to one relation

Respond | Trackback

  1. KD says:

    Good Article…

    For me lazy load is not working… Any Idea??

  2. [...] Fluent NHibernate – mapping one to one relation -23.548943 -46.638818 Compartilhe:FacebookTwitterDiggRedditTumblrGoogle +1Gostar disso:GosteiSeja o primeiro a gostar disso. [...]

  3. Kunal says:

    Hi Marcin,

    I’m stuck with a question about HasOne mapping. I haven’t got any answer from StackOverflow, so far. This post of yours comes close to the situation I’ve got. I’ve explained my problem here -> http://stackoverflow.com/questions/15959974/fluent-nhibernate-unit-test-hasone-mapping I don’t know how to unit test such a mapping. Any help will be greatly appreciated. Thanks in advance.

Respond

Comments

Comments