NHibernate Forge
The official new home for the NHibernate for .NET community

CurrentSessionContext for Desktop development

Wiki Page Hierarchy

Pages

Page Details

First published by:
Jason Meckley
on 11-06-2009
Last revision by:
Jason Meckley
on 11-06-2009
This page has not yet been rated
Article
Comments (22)
History (4)

CurrentSessionContext for Desktop development

I have used current session contexts in web applications with the ManagedWebContext class. I wanted to get this working in a non-asp.net environment though. And I wanted to keep the UI responsive, which means pushing as much as possible to the background.  I took a queue from Jeremy Miller's article on functional programming. To that end, here is one approach to managing Sessions in a threaded environment.

we will utilize the typical MVP triad injecting our view into the presenter.

    public class Presenter : IPresenter
    {
        private readonly IView view;
        private readonly IService service;
        private readonly ICommandExecutor executor;

        public Presenter(IView view, IService service, ICommandExecutor executor)
        {
            this.view = view;
            this.service = service;
            this.executor = executor;
        }

        public virtual void UpdateView()
        {
            executor.Execute(() =>
                                 {
                                     var text = service.GetData(1);
                                     return () => view.UpdateUserInterface(text);
                                 });
        }
    }

So what is the ICommandExecutor? This is where we centralize threading and session management. For SoC I have devided this into 2 implementations. one for threading the other for session management.

    public class AsynchronousExecutor : ICommandExecutor
    {
        private readonly SynchronizationContext synchronizationContext;
        private readonly ICommandExecutor executor;

        public AsynchronousExecutor(SynchronizationContext synchronizationContext, ICommandExecutor executor)
        {
            this.synchronizationContext = synchronizationContext;
            this.executor = executor;
        }

        public void Execute(Action action)
        {
            ThreadPool.QueueUserWorkItem(item => executor.Execute(action));
        }

        public void Execute(Func<Action> action)
        {
            ThreadPool.QueueUserWorkItem(item => executor.Execute(() =>
                        {
                           var continuation = action();
                           synchronizationContext.Send(x => continuation(), null);
                        }));
        }
    }

    public class UnitOfWorkExecutor : ICommandExecutor
    {
        private readonly ISessionFactory factory;

        public UnitOfWorkExecutor(ISessionFactory factory)
        {
            this.factory = factory;
        }

        public void Execute(Action action)
        {
            ExecuteWithinAUnitOfWork(action);
        }

        public void Execute(Func<Action> action)
        {
            ExecuteWithinAUnitOfWork(() => action());
        }

        private void ExecuteWithinAUnitOfWork(Action action)
        {
            try
            {
                using (var transaction = new TransactionScope())
                {
                    CurrentSessionContext.Bind(factory.OpenSession());
                    action();
                    transaction.Complete();
                }
            }
            finally
            {
                var session = CurrentSessionContext.Unbind(factory);
                if (session != null)
                {
                    session.Dispose();
                }
            }
        }
    }

AsynchronousExecutor pushes work to the background while UnitOfWorkExecutor sets up the context of a session. For information on synchronizationContext I will defer you to Jeremy's MSDN article. 2 steps left. 1) Configure NH and 2) wire this together.

To configure NH we will use Fluent NHibernate. The important part is setting the CurrentSessionContext property. For those not using programmatic configuration, you would set the property in the hibernate.config file along with the other session factory configs.

For wiring I'm using Castle Windsor. Any IoC should allow for something similar though. after placing the configuration and factory in the kernel we can use a factory method to resolve the session from the kernel. Note that the lifestyle of session is Transient. this is crucial, otherwise the sessions will not resolve correctly. We will use the same technique for resolving the SynchronizationContext as well.

 

    public class NHibernateFacility : AbstractFacility
    {
        protected override void Init()
        {
            var configuration = Fluently
                .Configure()
                .Database(() => MsSqlConfiguration.MsSql2000)
                .Mappings(m => m.FluentMappings.AddFromAssembly(GetType().Assembly))
                .ExposeConfiguration(ExtendConfiguration)
                .BuildConfiguration();

            Kernel.AddComponentInstance("configuration", configuration);
            Kernel.AddComponentInstance("factory", configuration.BuildSessionFactory());
            Kernel.Register(Component
                                .For<ISession>()
                                .LifeStyle.Is(LifestyleType.Transient)
                                .UsingFactoryMethod(k => k
.Resolve<ISessionFactory>()
.GetCurrentSession())); } private static void ExtendConfiguration(Configuration cfg) { var context = typeof(ThreadStaticSessionContext).AssemblyQualifiedName;
 cfg.SetProperty(Environment.CurrentSessionContextClass, context);
}
}

Finally, we wire up the entire container.

    internal static class Program
    {
        private static IWindsorContainer container;

        [STAThread]
        private static void Main()
        {
            container = new WindsorContainer()
                .AddFacility<FactorySupportFacility>()
                .AddFacility<NHibernateFacility>()
                .AddComponentLifeStyle<ICommandExecutor, AsynchronousExecutor>(LifestyleType.Singleton)
                .AddComponentLifeStyle<ICommandExecutor, UnitOfWorkExecutor>(LifestyleType.Singleton)
                .AddComponentLifeStyle<MainForm>(LifestyleType.Transient)
                .AddComponentLifeStyle<IPresenter, Presenter>(LifestyleType.Transient)
                .AddComponentLifeStyle<IService, Service>(LifestyleType.Transient)
                .Register(Component
                              .For<SynchronizationContext>()
                              .LifeStyle.Is(LifestyleType.Singleton)
                              .UsingFactoryMethod<SynchronizationContext>(CreateSynchronizationContext));

            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(container.Resolve<MainForm>());
        }

        private static SynchronizationContext CreateSynchronizationContext()
        {
            if (SynchronizationContext.Current == null)
            {
                var context = new WindowsFormsSynchronizationContext();
 SynchronizationContext.SetSynchronizationContext(context);
}
return SynchronizationContext.Current;
}
}

Recent Comments

By: unlockiphonetips Posted on 11-25-2011 4:42

The coding here is world class.

We do that too.  www.unlockiphonetips.com

Unlock iphone easy.  Unlock Iphone Cheap.

Seriously.  Good Coding.

By: roxymagina Posted on 04-19-2011 7:32

In terms of cuisine, I think the French have a good strange cuisine. Moreover, each dish also has a name that is hard for me to read. Understandably I'm not a French person. But I really like the culture.

www.mapleleafpromotions.com/Jute-Tote-Bag.html

By: RonalClock Posted on 04-03-2011 1:24

Doing a prevention will give lots of benefit for us. This include maintaining and others.

http://buyipad2s.com/

By: hermano Posted on 04-02-2011 8:36

Many things can be done to market your merchandise, advertising one of them. The best ads are the ads that show testimonials from customers, especially if there are examples of proof of delivery, will further attract potential buyers.

www.easyiphoneunlocking.com

By: C1arkRobert Posted on 04-02-2011 1:41

Getting a good asurance is good thing for us. Its really help us when something bad happen.

www.mylastweightloss.com/weightlosssummary

View All
Powered by Community Server (Commercial Edition), by Telligent Systems