Part II : Implementing Conversation per Business Transaction
Part III (without AOP) : Using Conversation per Business Transaction
Introduction
For this post I’ll use the same example of the Part III but using a real IoC framework (Castle Windsor). To abstract “aspect” the conversation stuff, from its implementation, I will use some custom Attribute defined in uNhAddIns.Adapters assembly. As you can see, downloading the example, there are few classes changed from the previous example, that are the more simple, and less intrusive, implementation of the FamilyCrudModel and, obviously, the implementation of ServiceLocatorProvider.Important
The implementation of “Aspect Conversation-per-BusinessTransaction” presented here is only one of the possible implementations. Gustavo Ringel (blog link not available so far) are working in a real-world example using Conversation-per-BusinessTransaction pattern in a Win-Form application with its implementation of uNhAddIns (the example is available here).“Model” implementation comparison
The new FamilyCrudModel complete implementation is:[PersistenceConversational] public class FamilyCrudModel<TAnimal> : IFamilyCrudModel<TAnimal> where TAnimal : Animal { private readonly IAnimalReadOnlyDao<TAnimal> animalDao; private readonly IFamilyDao<TAnimal> familyDao; public FamilyCrudModel(IDaoFactory factory) { animalDao = factory.GetDao<IAnimalReadOnlyDao<TAnimal>>(); familyDao = factory.GetDao<IFamilyDao<TAnimal>>(); } #region Implementation of IFamilyCrudModel<TAnimal> [PersistenceConversation] public IList<TAnimal> GetExistingComponentsList() { return animalDao.GetAll(); } [PersistenceConversation] public IList<Family<TAnimal>> GetEntirelyList() { return familyDao.GetAll(); } [PersistenceConversation] public Family<TAnimal> GetIfAvailable(int id) { return familyDao.Get(id); } [PersistenceConversation] public Family<TAnimal> Save(Family<TAnimal> entity) { if (entity == null) { throw new ArgumentNullException("entity"); } return familyDao.MakePersistent(entity); } [PersistenceConversation] public void Delete(Family<TAnimal> entity) { if (entity == null) { throw new ArgumentNullException("entity"); } familyDao.MakeTransient(entity); } [PersistenceConversation(ConversationEndMode = EndMode.End)] public void AcceptAll() { } [PersistenceConversation(ConversationEndMode = EndMode.Abort)] public void CancelAll() { } #endregion }Differences, from the previous implementation are:
- don’t need to inherits from any kind of base class.
- the constructor injection is more simple
- the implementation of each method don’t have boiled code
- the class and each persistent-method are marked with a custom attribute
The point(3) is, for example, this comparison:
From the point of view of Conversation-per-Business-Transaction usage that it’s all.
A more deep view
Behind the AOP I’m using, in this example, uNhAddIns.CastleAdapters. For who are familiar with Castle, the CastleAdapters assembly contains:- The TransactionProtectionWrapper and its factory; it is a ISession wrapper to ensure the transaction usage for certain ISession methods. The wrapper is used in all session-handlers implementations available in uNhAddIns (a NoWrappedSessionWrapper implementation is available in uNhAddIns core).
- The AutomaticConversationManagement Castle-Windsor-Facility.
- uNhAddIns-PersistenceConversation-nh-default.config file to use it as an include in the Windsor configuration, if you want use XML configuration.
container.AddFacility<PersistenceConversationFacility>(); var sfp = new SessionFactoryProvider(); sfp.AfterConfigure += ((sender, e) => new SchemaExport(e.Configuration).Create(false, true)); container.Register(Component.For<ISessionFactoryProvider>().Instance(sfp)); container.Register(Component.For<ISessionWrapper>().ImplementedBy<SessionWrapper>()); container.Register(Component.For<IConversationFactory>().ImplementedBy<DefaultConversationFactory>()); container.Register(Component.For<IConversationsContainerAccessor>().ImplementedBy<NhConversationsContainerAccessor>());Note that the class SessionFactoryProvider is the implementation for one-db application and I’m explicit instancing it only because I’m using the AfterConfigure event to create the DB (in production you don’t need to do it).
For who are not familiar with ICurrentSessionContext NHibernate's feature is important to remember that it need a specific NHibernate configuration property:
<property name="current_session_context_class"> uNhAddIns.SessionEasier.Conversations.ThreadLocalConversationalSessionContext, uNhAddIns </property>If you want download the example of this post, as usual, the code is available here.
once again (some problems with GMail ID), would it be possible to use PostSharp instead of Castle library?
ReplyDeleteSure, it is.
ReplyDeleteIn our TODO list there is:
Unity, LinFu, Spring, PostSharp depending on developers request/contributions.
As you can see uNhAddIns don't has a direct reference to Castle.
another question, is this pattern "o.k." to use in web applications? (ASP.NET MVC in particular)
ReplyDeleteor we should stick to "session per request", as you are mentioning that it only suits Winform developement (e.g. single user scenarios).
The pattern is sure useful in WEB too (check the first post of the series).
ReplyDeleteI have in ProductCrudModel this simple method :
ReplyDelete[PersistenceConversation(ConversationEndMode = EndMode.Continue)]
public IEnumerable[Product] FindByProductName(string name) {
return productReadOnlyDao.FindByName(name);
}
In FindByName(name) method, simple Criteria.List[Product]()
This works very slowly about 4 seconds.
If i work with CastleNhibernateIntegration facility it works very quick 20-40 ms.
Why the conversation works so slowly ?
In CpBT we are only managing the nh-session.
ReplyDeletePlease try to create a simple test.
Thanx Fabio for reply,
ReplyDeleteI create simple test for this situation:
http://groups.google.com/group/unhaddins/browse_thread/thread/e548a6f6a8a444fd
Is it possible to implement Conversation-per-BusinessTransaction in Silverlight. We are using NH and also sending the NH entities via WCF to the SL client. I know that some ses this as bad practice but it works and we see WCF as a transport layer not a service (SOA).
ReplyDeleteAnother question: Will there bee a implementation of NHV for Silverlight?
afaik, no.
ReplyDeleteExcellent article, thanks for the great job on this pattern.
ReplyDelete