locked
ORM and application context RRS feed

  • Question

  • Hi all,

    While playing a little bit with ORMs, i noticed some ASP.NET & NHibernate technique i doubt:
    In order to avoid opening multiple sessions (=conversation with a database ) during single web request
    some examles recommend of singleton , "session manager" which will hold single session during single
    web request. All the Repositories (=DAO, objects that needs database session) are taking their session
    from the "session manager". So far, so good.

    This is the code i found inside some recommended article:

    private ISession ContextSession {

    get {

    if (IsInWebContext()) {

    return (ISession)HttpContext.Current.Items[SESSION_KEY];

    }

    else {

    return (ISession)CallContext.GetData(SESSION_KEY);

    }

    }

    ...

    What i don't like here:
    1. DAL is aware of system.web.

    2. Must change configuration key between web mode and testing mode.

    3. No abstraction of "contexting" service.


    I would like to have your opinion regarding my approach:
    1. Implementing environement layer which is set of interfaces: ILogProvider , IConfigProvider, IContextProvider , etc
    2. All other layers depened on the environement layer and are being injected with this layer. Exmaple: The NHibernate
    repository is being injected with the environement services, such as logging, and configuration and context.
    3. Implement: public interface IContext {save (object identifier , object value) , get(object identifier)
    4. Then some client or factory are creating concurrent IContextProvider which is being injected for all the app components.

    5. Then the session manager code will look like the following:

    private ISession ContextSession {

    get {

    return someContextProvider.get(sessionDictionaryName)

    }

     

    Thanks for reading and commenting.

    Sunday, August 12, 2007 2:52 PM

Answers

  • Hi Ollie,
    Thanks for your reply, i'm using castle windsor IOC.

    Renaud Martinon,
    Your approach is very useful, however I find differences between the problems we try to solve.
    What i try to address here is "the relation between enviromental services and all the other layers" (since
    all layers need to use environement services such as log, error handling, context, cache, configuration files).
    I think your solution focus on transactions managment which lies mainly in the business layer. It's suitable
    for some cases while in few you may need to join your presentation layer in the session/transaction.

    Taking this discussion forward, i laid down some solution for the problem i described above, tell me what
    do you think.

    Environement is a class (actually a layer)  which is visible to all other layers. It holds associations to all the
    relevant services (log, etc.). Here's a diagram:
    http://www.goldbergyoni.com/site/portals/0/environement.jpg


    Environement will be accessed in two styles:
    1. Calling the static method which returns environement:
    Environement environementContext = myApp.Environement.getEnvironement()
    The static method will use IOC to pull all the relevant providers and build Environement object.

    2. By injecting Environement object into components: The GUI might initialize one Environement object
    (step 1) and pass it to the business logic and so forth.

    The static method which build the environement is the "dirty" place of the application.
    But at least it a single place.

    Yoni


    Monday, August 13, 2007 11:30 AM

All replies

  • Hi John,
     
    I certainly share your view that coupling ORM sessions with the inner workings of the web framework is not appropriate.
     
    For my current projet, I have used a BusinessContext abstraction that lives in the business layer and is in charge of managing sessions and transactions. Each business service item takes one such context as a property. This allows me to control session flow inside the business service, and to cascade calls between services using some simple inheritence tricks on the context. Also, I can very simply inject a specific test business context in my business service class for unit testing purposes.
     
    I still may have to adapt this architecture to allow for lazy loading outside of a service call but this has never been a strong requirement for my current projects.
     
    The solution you're outlining here certainly looks like a step in the right direction. Just make sure that your context provider returns appropriate sessions in each case (each business transaction should take place in its own session, sessions shouldn't be shared between users) and handles nesting well (one business service needs to execute a sub service in its own context, controlling the rollbacking and commiting of DB operations.)
     
    Feel free to contact me in you want to discuss this further.
    Monday, August 13, 2007 9:59 AM
  • Hi John,

     

    Your approach seems satisfactory to me and provides the abstraction you require from the host environment (asp.net) and the DAL. I presume from your question that you aren't currently using a Inversion of Control \ Dependacy Injection framework in your application. I have used Spring.net framework previously on multiple occasions to do exactly the kinda of thing you describe.

     

    http://www.springframework.net/

     

    HTH

     

    Ollie Riches

     

    Monday, August 13, 2007 10:25 AM
  • Hi Ollie,
    Thanks for your reply, i'm using castle windsor IOC.

    Renaud Martinon,
    Your approach is very useful, however I find differences between the problems we try to solve.
    What i try to address here is "the relation between enviromental services and all the other layers" (since
    all layers need to use environement services such as log, error handling, context, cache, configuration files).
    I think your solution focus on transactions managment which lies mainly in the business layer. It's suitable
    for some cases while in few you may need to join your presentation layer in the session/transaction.

    Taking this discussion forward, i laid down some solution for the problem i described above, tell me what
    do you think.

    Environement is a class (actually a layer)  which is visible to all other layers. It holds associations to all the
    relevant services (log, etc.). Here's a diagram:
    http://www.goldbergyoni.com/site/portals/0/environement.jpg


    Environement will be accessed in two styles:
    1. Calling the static method which returns environement:
    Environement environementContext = myApp.Environement.getEnvironement()
    The static method will use IOC to pull all the relevant providers and build Environement object.

    2. By injecting Environement object into components: The GUI might initialize one Environement object
    (step 1) and pass it to the business logic and so forth.

    The static method which build the environement is the "dirty" place of the application.
    But at least it a single place.

    Yoni


    Monday, August 13, 2007 11:30 AM
  • Hi John,

     

    What you describe seems fine to me, what is the purpose of the transactional dictionary and how is that going to be cleared after the transaction is committed\rolled back.

     

    Ollie Riches

    Monday, August 13, 2007 1:04 PM
  • You can use Castle Active Record over NHibernate and use the "isWeb" property in the XML configuration. That will take care of figuring out what type of SessionContext to use.

     

    Monday, August 13, 2007 8:14 PM