Friday, February 6, 2009

uNHaddins Persistence Conversation – Part 1: Configuration

uNHAddins Conversation and motivations where widely presented on Fabio’s blog here.

The focus of this series of posts is configuring the Persistence Conversation aspect using uNHAddins and CastleAdapter targeting a Windows Forms Application (some of the concepts are easily movable to a Web application, but there are much more frameworks and examples matching this)

A working example can be found in the examples folder of uNHAddins trunk, here.

The following assumptions are made about your repositories/Dao’s for this to work.

1) You are injecting the ISessionFactory in the repositories and not an ISession.

2) You are using GetCurrentSession() instead of OpenSession() to get the active session inside the repositories / dao’s.

3) You are able to use Castle for Dependency Injection, i hope more adapters will come in the future, but this is one that it is implemented and it is enough popular.

First thing we should do is to decide the conversation context strategy and set it in the hibernate cfg. For this example it is:

<property name="current_session_context_class"> 
uNhAddIns.SessionEasier.Conversations.ThreadLocalConversationalSessionContext, uNhAddIns 
</property>

Next thing is configuring castle to accept the PersistenceConversationalFacility, which will bring AOP in a similar manner to the TransactionalFacility from castle, and all the factories and services that compose a conversation.

The configuration for the facilities and default uNHAddins components for Castle can be found here . There are some cases when you will want to play with the factories, this will be the reason for another post.

Finally you set the way you are going to create sessions in your application (sessionFactory provider is the id to an implementation of ISessionFactoryProvider)
<component id="uNhAddIns.sessionFactory"
      type="NHibernate.ISessionFactory, NHibernate"
      factoryId="sessionFactoryProvider"
      factoryCreate="GetFactory">
      <parameters>
        <factoryId>uNhAddIns</factoryId>
      </parameters>
</component>
This is all the magic we need to set it up all. The following post will be about using it in our application.

If you want to see it working follow the link to the source at the beginning of the post.

2 comments:

  1. Thanks for the wonderful post.

    I succeeded in running sampel 'uNHAddins.Examples.SessionManagement', and now was trying to use MultiSessionFactoryProvider in example . What I did is :
    1. in file uNhAddIns-PersistenceConversation-nh-default.xml
    change SessionFactoryProvider --> MultiSessionFactoryProvider
    2. in file app.config , add
    [appSettings]
    [add key="nhfactory.1" value="test.cfg.xml"/]
    [/appSettings]
    3. rename file hibernate.cfg.xml to
    test.cfg.xml

    When I ran the example, I got error :

    A first chance exception of type 'Castle.MicroKernel.Facilities.FacilityException' occurred in Castle.MicroKernel.dll

    ReplyDelete
  2. I managed to make it work by setting the 'factoryId' to empty in core.config.

    ------------------------
    However I am still experiencing difficulty when trying to make this example to work in a multiple databases scenario.

    There are 2 databases , say A and B.

    ProductRepository uses database A
    OrderRepository uses database B

    2 cfg.xml files are set up for these 2 databases.

    Now the question is : how to setup core.config so that "product.repository" will use the factory returned from sessionFactoryProvider.GetFactory("A")
    while
    "order.repository" will use the factory returned from sessionFactoryProvider.GetFactory("B")


    I tried to define a dummy interface
    public interface SessionManagement.Data.NH.ISessionFactoryA:NHibernate.ISessionFactory{}

    and change Repository class defination as
    public class Repository[T,F] : IRepository[T] where F:ISessionFactory
    {
    public Repository(F factory)
    {
    this.factory = factory;
    }

    ....
    }

    Then I defined class
    public class ProductRepository : Repository[Product,ISessionFactoryA], IProductRepository
    {
    public ProductRepository(ISessionFactoryAf) : base(f) { }
    ...
    }

    and then setup in core.config
    [component id="A"
    type="SessionManagement.Data.NH.ISessionFactoryA, SessionManagement.Data.NH"
    factoryId="sessionFactoryProvider"
    factoryCreate="GetFactory"
    ]
    [parameters]
    [factoryId]A[/factoryId]
    [/parameters]
    [/component]


    when I ran it, I got error : 'Castle.MicroKernel.ComponentActivator.ComponentActivatorException' occurred in Castle.MicroKernel.dll.



    Please help me

    ReplyDelete