dotNetChris @ Marisic.Net

May 18, 2011

Exa-Mastery stage of software development patterns

Filed under: Architecture, Programming — Tags: , — dotnetchris @ 6:28 pm

One of the bloggers I make efforts to follow Steve Smith on the The 4 Stages of Learning Design Patterns. I’ve had the opportunity to meet Steve at previous DevConnections and he’s an all around good guy and from us speaking and all I’ve read through his blog posts I find our software development and architecture mentality to be very similar.

To sumarize Steve’s article he defines that are 4 stages to understanding software patterns.

  • Stage 0: I don’t know this pattern
  • Stage 1: I sort of know this pattern and can talk about it, maybe I can use it somewhere
  • Stage 2: I know this pattern, I think it’s awesome, I’m going to use it EVERYWHERE.
  • Stage 3: Understanding that too much of anything, even good things can be bad. That there are optimal usages of a given pattern and less fitting ways to use them.

This put my brain on the track of well what’s next? What’s past that last level of knowledge?

The next level comes from having obtained the experience to be a functioning Enterprise Architect. Having already obtained the knowledge and understanding of the application of said pattern(s) the next level comes from balancing the appropriate level of adoption of the pattern by your software team.

Successful usage of patterns at the exa-mastery level will result in:

    • improved code schematic cohesion

there’s nothing harder to digest than every project doing everything differently

    • design stays true to DRY YAGNI and KISS

if you’re continually violating these you’re failing as an architect because no matter how awesome you think your systems and frameworks if they aren’t built with these principles in mind you’re lieing to yourself and your team and your business. Writing software is hard, when you expect others to use your patterns they need to be simple¬†in usage regardless of whether they are ungodly complex or trivially simple under the seams.

    • ¬†pattern usage that is easy to understand

this is directly drives off my last point, the pattern doesn’t need to be easy the usage does. A perfect example of this is MVC and the conventions around the rather elaborate MVC software pattern, by following the conventions you can work even if you don’t understand why. This is an important requirement to have success that implementing your pattern can be done by your most junior dev to your most senior architect.

    • reducing code churn

good patterns hinge on DRY, or Don’t Repeat Yourself. Making this statement would have the corollary, good usage of software patterns lowers code churn. When software is built on top of repeatable success the lines of code that change should reduce because the amount of iterations to reach success should also reduce. Your pattern should be replacing the need to repeatedly do more work than neccessary. If your pattern is substantially increasing the work done for developers you need to have serious considerations on the usage.

    • patterns will have as few external moving parts as possible.

is another aspect of keeping it simple but discrete enough to merit it’s own line, the more pieces you have to manually connect the harder it is to stay successful with a pattern. A perfect example of this is shown by many ORMs. You create a class file that defines your object, you create an xml mapping file that relates your class to the database table, you have to remember to have the xml file set correctly in the project so when you goto deploy that it’s still there and can be accessed correctly. The more disjoint pieces you make your team responsible for to use your patterns you exponentially increase the amount of failure. I can’t tell you how many times I saw people ready to pull their hair out in NHibernate forums and other discussion forums on why their mapping isn’t working and it comes down a hbm file being set to the wrong resource type.

BloggingContext.ApplicationInstance.CompleteRequest();

December 18, 2009

Implementing NHibernate Long Conversation with no HttpModules or AOP build time weaving

GIANT WARNING STICKER

This code is some major caveats to be taken when considered for production usage. If this would be used to solely power a shopping cart application it should work fine however if it will also govern the objects such as having administration functionality to update products etc it can lead to very inconsistent results due to users having the object in their first level cache (the ISession object) that you have modified and there seems to be no way to handle this correctly.

I have an open stack overflow question regarding this nature however there has been no positive feedback and even the direct NHibernate documents say “As the ISession is also the (mandatory) first-level cache and contains all loaded objects, we can propably use this strategy only for a few request/response cycles. This is indeed recommended, as the ISession will soon also have stale data.” So all in all it seems like a giant failure to attempt and after years worth of effort to solve this I have given up unless my SO thread is ever answered meaningful.

This post has been almost a year coming and it’s finally here. I still haven’t been posting much even being in the full swing of development, I just usually end up drained between work and overtime when I have years worth of development plans for my company that they would love to have all of them tomorrow. Fortunately my current employer is definitely is the best environment I’ve ever been in aside from that they give me all the tools I need to complete job they give me basically full reign on system architecture that I finally get to develop and put into production code I’ve worked off and on for over a year now. Also they have very realistic expectations that I’m not rushed to make poor decisions to push a product out the door that’s poorly designed. Now getting back on track.

It all started with Conversation Per Business Transaction using PostSharp and IoC written almost a year ago from today. This post at the time was definitely one of my largest successes in my development career however even though I solved the problem I wanted I still was not happy with the solution (probably because with PostSharp atleast back then my solution would take 5 minutes+ to build) still it was somewhat fragile for how I had to decorate classes with my [BusinessConversation] attributes that a nested method call would cause all hell to break loose.

To start I’m going to show you my final product, this is one of my model classes in the Model-View-Presenter software pattern

public class NotificationModel : INotificationModel
{
    private readonly INotificationProvider _NotificationProvider;

    public NotificationModel(INotificationProvider NotificationProvider)
    {
        _NotificationProvider = NotificationProvider;
    }

    [ConversationPersistance(ConversationCommitMode.Rollback)]
    public void AddButRollBack(NotifyRun notifyRun)
    {
        _NotificationProvider.Add(notifyRun);
    }

    public void Add(NotifyRun notifyRun)
    {
        _NotificationProvider.Add(notifyRun);
    }
}

As you can see on the AddAndRollBack method I do decorate the method with a custom attribute which does make my model somewhat aware of my implementation of my repository but I feel this is an acceptable pollution as it is reasonable to expect any method in the MVP pattern to know whether it’s role is to get data, save data or cancel an action. As you can see though the other method has no decoration and doesn’t require any decoration for the default action you configure.

Next I’m going to start with my inversion of control container, I use StructureMap however I believe this should also be able to be acheived using most other major DI frameworks.

private sealed class StructureMapRegistry : Registry
{
    public StructureMapRegistry()
    {
    //Configure default persisance mode
        ForRequestedType<ConversationCommitMode>().TheDefault.IsThis(ConversationCommitMode.Commit);

    //Castle DynamicProxy
        ForRequestedType<ProxyGenerator>().TheDefaultIsConcreteType<ProxyGenerator>()
      .CacheBy(InstanceScope.Singleton);

    //Castle DynamicProxy IInterceptor 
        ForRequestedType<ConversationInterceptor>().TheDefaultIsConcreteType<ConversationInterceptor>()
      .CacheBy(InstanceScope.Singleton);

     //Configuration wrapper of NH, this could be configured inline here but it's rather verbose
        ForRequestedType<INHibernateSessionManager>().TheDefaultIsConcreteType<NHibernateSessionManager>()
      .CacheBy(InstanceScope.Singleton);

    //This is a lightweight wrapper of the NH ISession that supports lazy access with the session
        ForRequestedType<IBusinessConversation>().TheDefaultIsConcreteType<LazyBusinessConversation>()
      .CacheBy(InstanceScope.HybridHttpSession);

    //This is my NH repository
        ForRequestedType<INotificationProvider>().TheDefaultIsConcreteType<NotificationProvider>()
      .CacheBy(InstanceScope.Hybrid);

    //This is a model class in the MVP pattern  that uses the above NH Provider
        ForRequestedType<INotificationModel>().TheDefaultIsConcreteType<NotificationModel>().CacheBy(InstanceScope.Hybrid)
            .EnrichWith((ctx, model) =>
      ctx.GetInstance<ProxyGenerator>().CreateInterfaceProxyWithTarget(model, ctx.GetInstance<ConversationInterceptor>()));

    //Set rules for what properties are injected on ObjectFactory.BuildUp(this)
        SetAllProperties(policy => policy.NameMatches(name => name.EndsWith("Provider") || name.EndsWith("Model")));
    }
}

I’m not going to explain my NotificationProvider class as it’s irrelevant to this post, it’s a class entirely derived from Creating a common generic and extensible NHiberate Repository, the SetAllProperties is just a StructureMap convention, ConversationCommitMode lets you inject your default configuration to the conversation, and the SessionManager also is unrelated to this post it’s just a wrapper class for boostrapping my NH session factory with Fluent NHibernate. The ProxyGenerator is a class in Castle DynamicProxy, I just use the version that’s already included with my NH. So now I’ll start with my Conversation class that has changed since my previous post. The biggest change is the client no longer needs to be aware of starting the session, connecting or disconnecting the session in anyway. The only need to care about what happens with the ISession after it is consumed.

public interface IBusinessConversation
{
    bool IsInTransaction { get; }
    bool IsNull { get; }
    ISession Session { get; }

    void Abort();
    void Commit();
    void CommitAndFlush();
    void End();
    void Rollback();
}

Part of the reason behind my BusinessConversation class is that I can implement the Null object pattern and lazy loading of the ISession itself so the session is delayed creation until one of my Repositories actually goes to use it and after it exists it’s only connected in instances that actually need it, not on every single page request! Onto the actual implementation.


public sealed class LazyBusinessConversation : IBusinessConversation
{
  private readonly INHibernateSessionManager _sessionManager;
  private ISession _session;

  public LazyBusinessConversation(INHibernateSessionManager sessionManager)
  {
    _sessionManager = sessionManager;
  }

  #region IBusinessConversation Members

  /// <summary>
  /// Rollback and do not commit the current transaction
  /// </summary>
  public void Rollback()
  {
    Rollback(_session);
  }

  /// <summary>
  /// Gets a value indicating whether this instance is in transaction.
  /// </summary>
  /// <value>
  ///   <c>true</c> if this instance is in transaction; otherwise, <c>false</c>.
  /// </value>
  public bool IsInTransaction
  {
    get { return _session.Is().Not.Null && _session.Is().InTransaction; }
  }

  /// <summary>
  /// Gets a value indicating whether this instance is null.
  /// </summary>
  /// <value><c>true</c> if this instance is null; otherwise, <c>false</c>.</value>
  public bool IsNull
  {
    get { return _session.Is().Null; }
  }

  /// <summary>
  /// Aborts this instance.
  /// </summary>
  public void Abort()
  {
    Abort(ref _session);
  }

  /// <summary>
  /// Commits the open transaction the session. Does not flush the session
  /// </summary>
  public void Commit()
  {
    Commit(_session, false);
  }

  /// <summary>
  /// Commits any open transaction in the session and
  /// flushes all pending changes to the database
  /// </summary>
  public void CommitAndFlush()
  {
    Commit(_session, true);
  }

  /// <summary>
  /// Ends this instance committing and flushing all data in session.
  /// </summary>
  public void End()
  {
    End(ref _session);
  }

  public ISession Session
  {
    get
    {
      if (!IsInTransaction)
      {
        Resume(_sessionManager, ref _session);
      }

      return _session;
    }
  }

  #endregion

  #region Class Methods

  private static void Abort(ref ISession session)
  {
    if (session.Is().NullOrClosed) return;

    Rollback(session);
    TerminateSession(ref session);
  }

  private static void Commit(ISession session, bool flush)
  {
    if (session == null)
      throw new ArgumentNullException("session");

    if (session.Is().InTransaction)
      session.Transaction.Commit();

    if (flush)
      session.Flush();

    session.Disconnect();
  }

  private static void End(ref ISession session)
  {
    if (session.Is().NullOrClosed) return;

    Reconnect(session);

    Commit(session, true);

    TerminateSession(ref session);
  }

  private static void Reconnect(ISession session)
  {
    if (session == null)
      throw new ArgumentNullException("session");

    if (session.IsConnected) return;

    session.Reconnect();
  }

  private static void Resume(INHibernateSessionManager sessionManager, ref ISession session)
  {
    if (session.Is().NullOrClosed)
      session = sessionManager.GetSession();

    if (session.Is().Null)
      throw new AccessViolationException("Session could not be created");

    Reconnect(session);

    if (session.Is().Not.InTransaction)
      session.Transaction.Begin();
  }

  private static void Rollback(ISession session)
  {
    if (session == null)
      throw new ArgumentNullException("session");

    if (session.Is().InTransaction)
      session.Transaction.Rollback();
  }

  private static void TerminateSession(ref ISession session)
  {
    session.Close();
    session.Dispose();

    /// Safety net incase conversation is reused
    /// this will guarantee a new session is created
    session = null;
  }

  #endregion
}

Sorry, long block of code I know, before I get into the specifics of it the majority of this class is pretty simple I inject my SessionFactory to the Conversation so I can new sessions when I need them. Other than that the majority of the methods do exactly what they are named and just complete the session or transaction in 1 way or another. Also I’m sure you noticed I call session.Is() this is an extension method that allows me to fluently check session state instead of having to do if(session != null && session.IsInTransaction) etc. Where all of the work really occurs is ISession { get }

IsInTransaction will always return false the first time .Session is accessed during a page request because either the session will be null or it will be disconnected. So the first time it’s accessed it calls Resume. Inside Resume I check to see if it exists, if not, new a session. If it already existed it needs to be reconnected. This handles all of the lazy loading (or lazy reconnection) this is a big advantage over pretty much every solution I’ve seen for the Long Conversation pattern is that they are based on instantiating a session for every user, connecting it at the start of every page request and committing it at the end of every page request regardless of whether or not they need the session at all! Also many of these patterns rely on HttpModules which makes testing so much harder!

At some point this class could probably use some refactoring to split out the methods that actually reattach the session, currently I have a few them with static methods and ref pointers so that you couldn’t call Resume(_sessionManager, Session) from inside the class easily and cause all kinds of unnecessary recursion. Of course as I type this I realize an explicitly defined Session { get } would go a long way for that, I also might consider wrapping my static methods into a class of their own and actually injecting that into the conversation. Now that you can see what my conversation class does we’ll take a look at what’s going on with

ForRequestedType<INotificationModel>().TheDefaultIsConcreteType<NotificationModel>().CacheBy(InstanceScope.Hybrid)
  .EnrichWith(
  (ctx, model) =>
  ctx.GetInstance<ProxyGenerator>().CreateInterfaceProxyWithTarget(model, ctx.GetInstance<ConversationInterceptor>()));

Per the StructureMap documentation

EnrichWith() — Registers a Func that runs against the new object after creation and gives you the option of returning a different object than the original object

So what happens here is you’re intercepting StructureMap giving you an instance of the NotificationModel and doing something with it. In this case what we’re going to do with it is use Castle DynamicProxy to actually create an entirely new NotificationModel that will wrap all of our methods with what we do in the ConversationInterceptor!

public class ConversationInterceptor : IInterceptor
{
  private readonly ConversationCommitMode _conversationCommitMode;

  public ConversationInterceptor(ConversationCommitMode conversationCommitMode)
  {
    _conversationCommitMode = conversationCommitMode;
  }

  private ConversationCommitMode GetConversationMode(ICustomAttributeProvider methodInfo)
  {
    var attribute = methodInfo.GetCustomAttributes(typeof (ConversationPersistanceAttribute), true);

    return attribute == null || attribute.Length == 0
           ? _conversationCommitMode
           : ((ConversationPersistanceAttribute) attribute[0]).ConversationMode;
  }

  #region IInterceptor Members

  public void Intercept(IInvocation invocation)
  {
    invocation.Proceed();

    var conversation = ObjectFactory.GetInstance<IBusinessConversation>();

    if (conversation.IsNull) return;

    switch (GetConversationMode(invocation.Method))
    {
      case ConversationCommitMode.CommitAndFlush:
        conversation.CommitAndFlush();
        break;
      case ConversationCommitMode.Rollback:
        conversation.Rollback();
        break;
      case ConversationCommitMode.Abort:
        conversation.Abort();
        break;
      case ConversationCommitMode.Commit:
      default:
        conversation.Commit();
        break;
    }
  }

  #endregion
}

So what happens after the ProxyGenerator creates our new class is instead of directly calling each method in the Model it will execute the code in Intercept(IInvocation) which for our case will first immediately run the method because we only need to do more AFTER it completes. Now as it runs the method it will call down to the Provider which will then use the lazyBusinessConversation.Sesssion property which will activate our session, run it’s NH commands and start to trace the call chain back after it finishes the execution of the original method call for any of the Model methods it returns back to the Intercept method.

The first thing we’ll check is if the session is null because if it is (meaning we didn’t touch it in our method) we don’t need to do anything else! I’ll explain why this will be very useful in a minute. Assuming we did an NH operation we’re going to check to see if I have our custom attribute added to the method like I do for AddAndRollBack in the model. If it’s there it will return that otherwise it will return the default commit operation that we injected into our IoC container. The switch statement is self explanatory. If we didn’t actually interact with NH on our round trip but the session was created before it still calls conversation.Commit() but looking above you can see it verifies it has an open transaction otherwise it will do nothing, this covers our lazy connection handling without having to embed that logic inside the interceptor.

Now the reason why I handle the null checking as some of you may have wondered, why would the session ever be null when the model is basically just a wrapper around the NH provider classes, the flexibility my solution offers is if you move the .EnrichWith() method in our StructureMap registry off of the Model classes you can put them on either your View or Presenter classes so that the session will be connected for basically the full page life cycle so you should get full support from lazy loading! Also since alot of methods in your views or presenters will have nothing to do talking to NH it will skip all of the work with NH on those requests! This is where I would Enrich my classes outside of my test project.

I would really like to thank Sam over on the StructureMap forums for his very insightful post that gave me the knowledge I needed to see how to solve the Long Transaction pattern using the castle dynamic proxy framework!

Right now none of this code is in my StructuredWeb SVN currently but I will merge all my current work back into SW soon!

kick it on DotNetKicks.com

Shout it

BloggingContext.ApplicationInstance.CompleteRequest();

February 16, 2009

Creating a generic Model-View-Presenter framework

With all of the current talk about ASP.NET MVC it seem dated to bring up the model view presenter architecture but I still believe it’s a very strong pattern in separating UI logic from application design. This post is meant to offer a successor to the Web Client Software Factory (WCSF) framework provided by Microsoft. In last usage of WCSF I encountered numerous errors stemming from ObjectBuilder during the dependency injection of WCSF which is what lead me down the road of creating UnityWeb which has evolved into StructuredWeb. The rest of this post will include no specific dependencies except 1 to StructureMap to handle the actual resolution of objects through dependency injection. This could be very easily replaced by Unity or any other inversion of control framework that supports the BuildUp() method. For a framework that does not support a BuildUp operation it will make things more complicated and that will need to be solved by your case basis.

Firstly, what is the model-view-presenter (MVP) pattern? The View is defined as an interface that the Presenter will use for getting and setting data to and from the Model. The View implementation will instantiate the Presenter object and provide a reference to itself (the formal constructor parameter is the View interface while the actual parameter is a concrete View class). When the event methods of the View are triggered, they will do nothing but invoke a method of the Presenter which has no parameters and no return value. The Presenter will then get data from the View, through the View interface variable that the Presenter stored when the constructor was called. The Presenter then invokes methods of the Model, and sets data from the Model into the View through the View interface.

From a layering point of view, the Presenter class might be considered as belonging to the application layer in a multilayered architectured object-oriented system with common layers but it can also be seen as a Presenter layer of its own between the Application layer and the User Interface layer.

[/source]

Now if you’re at all like me you will have almost no more of an idea what the MVP pattern is supposed to do after that explanation. To generalize on that statement it’s basically taking the interaction of the UI and the application logic which usually is coupled together and separating it into 3 areas.

The model – this is the application logic which will be housed in controller classes.

The view – which is an interface which abstracts the UI away, all data sent and retrieved from the UI is done through this interface

The presenter – this is a mediator that negotiates how the UI and application logic interact. The view is also a composition of this class.

Starting with the view:

public interface IView
{
}

This is the most basic of the basic of interfaces, for my needs it’s purely a marker interface. If every single one of your pages shares a common property perhaps an event message collection this would be a good place to define a property for it.

The presenter class:

public abstract class Presenter<TView> where TView : IView
{
    public TView View { get; set; }

    public virtual void OnViewInitialized()
    {
    }

    public virtual void OnViewLoaded()
    {
    }
}

The OnViewInitialized method is to represent any operations you would execute in Page_Load if(Page.IsPostback == false) so only on the initial page load. The OnViewLoaded method represents all page loads whether or not they are post backs. Currently I have no global page operations since I have no global view properties. This class is also constrained that each TView for a presenter is also an IView, this will be important later.

Next creating a view:

public interface IEmployeeView: IView
{
    IList<Employee> Employees { get; set; }
    IList<Employee> EmployeesListDatasource { set; }
}

As you can see my view will have 2 properties one for getting or setting a collection and another for setting only the same type. The view also implements the marker interface IView.

Creating the presenter:

public class EmployeePresenter : Presenter<IEmployeeView>
{
    private readonly IEmployeeController _controller;

    public EmployeePresenter(IEmployeeController controller)
    {
        _controller = controller;
    }

    public override void OnViewInitialized()
    {
        View.Employees = _controller.GetEmployees();
    }

    public override void OnViewLoaded()
    {
        View.EmployeesListDatasource = View.Employees;
    }
}

I’m not going to go into the details of the IEmployeeController this is the “model” where actual application code is ran there is nothing special about this class or it’s interface and only contains logic specific to getting my set of employees. As you can see the EmployeePresenter implements Presenter. I overrided both of the methods provided by the Presenter base where the Initialize method gets list from the model and the loaded method binds the list to a datasource.

Now before I move onto implementing the IEmployeeView inside a page I’m going to create an abstract base page that will handle the dependency injection build up for my MVP framework.

public abstract class ViewBasePage<TPresenter, TView> : Page
    where TPresenter : Presenter<TView>
    where TView : IView
{
    protected TPresenter _presenter;

    public TPresenter Presenter
    {
        set
        {
            _presenter = value;
            _presenter.View = GetView();
        }
    }

    /// <summary>
    /// Gets the view. This will get the page during the ASP.NET
    /// life cycle where the physical page inherits the view
    /// </summary>
    /// <returns></returns>
    private static TView GetView()
    {
        return (TView) HttpContext.Current.Handler;
    }

    protected override void OnPreInit(EventArgs e)
    {
        ObjectFactory.BuildUp(this);
        base.OnPreInit(e);
    }
}

This class might look quite a bit strange, the majority of it is from the class definition it’s setup to only allow you to inherit it in a valid way such as: ViewBasePage<EmployeePresenter,IEmployeeView>. On the Presenter set method this is where the page actually becomes part of the composition of the Presenter (the description from Wikipedia said this).

The GetView method also probably looks strange what this is doing is getting the physical page that’s being instantiated by ASP.NET. The reason I’m doing this is it makes it easier to reference the page generically otherwise I would be required to do something smilar to

return (TView) (object) this

Which is borderline wrong since THIS technically refers to the ViewBasePage which does not implement the interface that TView consists of but at runtime eventually resolves correctly since a Page will implement the interface that makes up TView and not cause a runtime error.

This class overrides Page’s OnPreInit method to call ObjectFactory.BuildUp() which will cause all the dependency resolution to take place. In my specific usage of StructureMap I have it identify all Presenter properties as targets for dependency injection, in your case you may be required to use the [Setter] attribute from SturctureMap or the [Dependency] attribute from Unity or some other similar convention in other inversion of control frameworks.

Now finally onto the actual page.

public partial class _Default :
    ViewBasePage<EmployeePresenter, IEmployeeView>, IEmployeeView
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!Page.IsPostBack)
        {
            _presenter.OnViewInitialized();
        }

        _presenter.OnViewLoaded();
        Page.DataBind();
    }

    #region Implementation of IEmployeeView

    IList<Employee> IEmployeeView.Employees
    {
        get { return ViewState["IEmployeeView.Employees"] as IList<Employee>; }
        set { ViewState["IEmployeeView.Employees"] = value; }
    }

    IList<Employee> IEmployeeView.EmployeesListDatasource
    {
        set { lstEmployees.DataSource = value; }
    }

    #endregion
}

This class inherits the ViewBasePage class and implements the IEmployeeView. The _presenter field is in the ViewBasePage and contains the fully resolved dependency to EmployeePresenter. As I stated in the portion of the presenter code you can see where OnViewInitialized() and OnViewLoaded() are called inside the page life cycle.

Implementing the IEmployeeView you have the properties target actual controls on the page or the ViewState / QueryString etc that is available to the page. Now if you remember the code in my actual EmployeePresenter it should make sense why in ViewInitialized the Employees property is set by the controller and on the ViewLoaded the Employees property is assigned to the EmployeesListDatasource since it’s just refreshing the data source to the view state collection on subsequent page post backs.

kick it on DotNetKicks.com

Shout it

BloggingContext.ApplicationInstance.CompleteRequest();

February 3, 2009

StructuredWeb Alpha 1

After my long road down the rabbit hole of object orientated design, inversion of control, NHibernate, Fluent NHibernate I’ve finally reached a point where I feel my codebase is stable enough to almost warrant my beta 1 release. I switched from Unity as my DI container to StructureMap and definitely feel this was a good call especially the timing of the 2.5.3 release of StructureMap where it natively includes the BuildUp method and natively includes the functionality I had to add with custom lifetime managers for wrapping my objects into the HttpContext and HtttpSession.

Just recently I published my implementation of Business Conversation per Transaction session management along with my repository pattern I followed for StructuredWeb. I still haven’t gotten my second level caching for NHibernate running yet but that will on slate for Beta 2.

See my StructuredWeb Installation page for details for setting it up.

This still needs a little bit of work for me to qualify it as a beta but since I checked everything into Assembla I figured I’d announce it’s alpha release since the code is already available online.

BloggingContext.ApplicationInstance.CompleteRequest();

January 28, 2009

Creating a common generic and extensible NHiberate Repository

In my previous post Conversation Per Business Transaction using PostSharp and IoC I dealt with the session management aspect of NHiberate however by the end of my development of the business conversation aspect I realized that my current data provider scheme created a lot of duplicate code. As we all know any code that is duplicated becomes a nightmare to maintain so I went through and refactored first a truly generic repository.

public interface IRepository<T>
{
    ICriteria GetAll();
    T Get<U>(U id);
    void Save(T obj);
    ICriteria GetRange(int resultSet, int rangeSize);
}

This is a rather basic interface that will handle the most common operations to my data providers, currently it can handle getting all of the items in my database for a type, a page collection into the list of items in my database, get a specific item and save a new item (or update an existing item). The only minorly unsightly part is the Get<U> method this just allows passing any type of ID instead of declaring it as int statically.

On to implementing the interface:

public class Repository<T> : IRepository<T>
{
    private readonly IConversation _conversation;

    public Repository(IConversation conversation)
    {
        _conversation = conversation;
    }

    #region IRepository<T> Members

    ICriteria IRepository<T>.GetAll()
    {
        return _conversation.Session.CreateCriteria(typeof (T))
            //.SetCacheable(true)
            //.SetCacheMode(CacheMode.Normal)
            ;
    }

    T IRepository<T>.Get<U>(U id)
    {
        return _conversation.Session.Get<T>(id);
    }

    void IRepository<T>.Save(T obj)
    {
        _conversation.Session.SaveOrUpdate(obj);
    }

    ICriteria IRepository<T>.GetRange(int resultSet, int rangeSize)
    {
        return _conversation.Session.CreateCriteria(typeof (T))
            //.SetCacheable(true)
            //.SetCacheMode(CacheMode.Normal)
            .SetFirstResult(resultSet*rangeSize)
            .SetMaxResults(rangeSize - 1)
            ;
    }

    #endregion
}

This class contains rather basic interactions with NHiberate, if you’re not familiar with the CreateCriteria querying method in NHibernate take a look at Chapter 12. Criteria Queries. Other than that I can at an application level enable or disable output caching for my generic repository, currently I’m still working on getting my second level caching implementation working so right now I have it disabled as you can see it’s commented out.

By returning the ICriteria from the repository it allows us to pass on the full power of NHibernate and allow us to create further data provider specific queries.

Next I created an abstract base class for my actual data providers:

public abstract class DataProviderBase<T>
{
    protected readonly IConversation _conversation;
    protected readonly IRepository<T> _repoistory;

    protected DataProviderBase(IConversation conversation)
    {
        _conversation = conversation;
        _repository = new Repository<T>(_conversation);
    }
}

This base class just holds the fields for the business conversation (or ISession) and my newly created generic repository. Now on to my true concrete implementation of my data provider:

public class EmployeeDataProvider : DataProviderBase<Employee>, IEmployeeDataProvider
{
    [InjectionConstructor]
    public EmployeeDataProvider(IConversation conversation) : base(conversation)
    {
    }

    #region IEmployeeDataProvider Members

    IList<Employee> IEmployeeDataProvider.GetAll()
    {
        return _repository.GetAll().List<Employee>();
    }

    IList<Employee> IEmployeeDataProvider.GetRange(int resultSet, int rangeSize)
    {
        return _repository.GetRange(resultSet, rangeSize).List<Employee>();
    }

    Employee IEmployeeDataProvider.Get(int employeeId)
    {
        return _repository.Get(employeeId);
    }

    void IEmployeeDataProvider.Save(Employee employee)
    {
        _repository.Save(employee);
    }

    IList<Territory> IEmployeeDataProvider.GetTerritories()
    {
        return _conversation.Session.CreateCriteria(typeof (Territory)).List<Territory>();
    }

    #endregion
}

In this class we have the delegation of the IRepository (sitting in the abstract base) and we also have direct access to the NHibernate Session so we can add further methods of any kind. This also allows us the flexibility if you’d rather the EmployeeDataProvider had GetEmpoyees() instead of GetAll() it would allow that easily.

Since the repository itself is not exposed at the provider level this allows us to return the actual results in anyway we want. It allows us to further modify the basic queries by adding NHibernate where clauses to the Criteria if we so choose. Since the actual ICriteria won’t be exposed outside of the data provider we don’t need to worry about client interactions causing database usage. This would also allow us if we added NHibernate LINQ to not be concerned with returning the Queryable results for the same reason.

This pattern would also work directly with LINQ2SQL / LINQ2Entities / DLINQ by changing where the NHibernate session is dealt with and using your entity provider. I feel this is a perfect to the data access patern as it protects the code from becoming too unweilding by basing all communication directly through the ICriteria and giving our data providers concrete result lists.

Let me know what you think!

kick it on DotNetKicks.com

Shout it

BloggingContext.ApplicationInstance.CompleteRequest();

The Shocking Blue Green Theme Blog at WordPress.com.

Follow

Get every new post delivered to your Inbox.

Join 242 other followers

%d bloggers like this: