I created an interface called IContextWrapper.
My applications and business layers are only talking to that
interface.
the interface now looks like this (but will be extended :-))

public interface IContextWrapper: IDisposable
    {
        string ConnectionString { get; set; }

        T CreateObject<T>() where T : IEntity;
        T GetObjectById<T>(object identity);
        T GetObjectByKey<T>(string keyPropertyName, object keyValue);
        T TryGetObjectById<T>(object identity);
        T TryGetObjectByKey<T>(string keyPropertyName, object
keyValue);
        IList<T> GetObjectsByQuery<T>(string npathQuery);
        IList<T> GetObjectsBySql<T>(string sql);

        void DeleteObject(IEntity entity);
        void Commit();
        void CommitObject(IEntity entity);
        void Clear();
        bool ValidateBeforeCommit { get; set; }

        bool IsDeleted(IEntity entity);
        bool IsUpForCreation(IEntity entity);
        bool IsDirty(IEntity entity);
        bool IsClean(IEntity entity);

        object GetObjectIdentity(IEntity entity);
    }

Now I have an implementation if IContextWrapper for each ORM
(NHibernate, EF, NPersist etc)
My Entities all implement IEntity and are derived form EntityBase:

public interface IEntity
    {
        object ObjectIdentity { get; }
        IContextWrapper ContextWrapper { get; set; }
        bool IsDeleted { get; }
        bool IsUpForCreation { get; }
        bool IsDirty { get; }
        bool IsClean { get; }
    }

public abstract class EntityBase: IEntity
    {
        protected IContextWrapper _ContextWrapper;

        protected virtual object GetObjectIdentity()
        {
            return _ContextWrapper.GetObjectIdentity(this);
        }

        public object ObjectIdentity
        {
            get
            {
                return this.GetObjectIdentity();
            }
        }

        public virtual IContextWrapper ContextWrapper
        {
            get
            {
                return _ContextWrapper;
            }
            set
            {
                _ContextWrapper = value;
            }
        }

        public bool IsDeleted
        {
            get { return _ContextWrapper.IsDeleted(this); }
        }

        public bool IsUpForCreation
        {
            get { return _ContextWrapper.IsUpForCreation(this); }
        }

        public bool IsDirty
        {
            get { return _ContextWrapper.IsDirty(this); }
        }

        public bool IsClean
        {
            get { return _ContextWrapper.IsClean(this); }
        }
    }

As you can see, when after an entity is instantiated I need to set the
ContextWrapper property of the Entity, otherwise the whole system
won't work.
Now I do this by implementing ILoadEventListener. Here is my
constructor for th NHibernate implementation of IContextWrapper:

public ContextWrapper(string assemblyName, string connectionString)
        {
            _CacheInserted = new EntityCache(this);
            _CacheDeleted = new EntityCache(this);

            NHibernateHelper.AddAssembly(assemblyName);
            NHibernateHelper.SetConnectionString(connectionString);

            // TODO: investigate memory leaks and garbage collection
            ILoadEventListener[] stack = new ILoadEventListener[]
{ new global::NHibernate.Event.Default.DefaultLoadEventListener(), new
EntityLoadListener(this) };
            NHibernateHelper.GetConfiguration
().EventListeners.LoadEventListeners = stack;

            IPostLoadEventListener[] stack2 = new
IPostLoadEventListener[] { new
global::NHibernate.Event.Default.DefaultPostLoadEventListener(), new
EntityPostLoadListener(this) };
            NHibernateHelper.GetConfiguration
().EventListeners.PostLoadEventListeners = stack2;

            _Session = NHibernateHelper.GetSessionFactory().OpenSession
();
        }

And here's the implementation of ILoadEventListener:

public class EntityLoadListener : ILoadEventListener
    {
        IContextWrapper _ContextWrapper;

        public EntityLoadListener(IContextWrapper contextWrapper)
        {
            _ContextWrapper = contextWrapper;
        }

        // this is the single method defined by the LoadEventListener
interface
        public void OnLoad(LoadEvent @event, LoadType loadType)
        {
            if (loadType.IsAllowProxyCreation)
            {

                ISessionImplementor source = @event.Session;

                IEntityPersister persister =
source.Factory.GetEntityPersister(@event.EntityClassName);

                EntityKey keyToLoad = new EntityKey(@event.EntityId,
persister, source.EntityMode);

                IPersistenceContext persistenceContext =
@event.Session.PersistenceContext;

                // look for a proxy
                object proxy = persistenceContext.GetProxy(keyToLoad);

                if (proxy is IEntity)
                {
                    (proxy as IEntity).ContextWrapper =
_ContextWrapper;
                }
            }
        }
    }

So as you can see, if a proxy is loaded, I can set the ContextWrapper
of my Entity.
But if I have not proxy, the event will not fire and I'm not able to
set the ContextWrapper property.
Maybe now you understand why I need proxies all the time.

Harm.

On Sep 23, 9:16 pm, José F. Romaniello <[email protected]> wrote:
> Let's go back. You say that this code is in your base class, a base class
> for what?
> What kind of classes inherit from this base? repositories, entities,
> services?
>
> 2009/9/23 Harm Neervens <[email protected]>
>
>
>
>
>
> > > Your design is somewhat flawed, maybe you'd like to revise it.
>
> > This is not my design, but just some code snippet to express what my
> > intentions are.
> > I'm not posting this question to get critics at my design, but to get
> > a decent answer at my question.
> > I'm always told that open source communities were so helpfull :-(
>
> > On Sep 23, 9:01 pm, "Francisco A. Lozano" <[email protected]> wrote:
> > > If your base classes are coupled to nhibernate, so is any class that
> > > derives from them.
>
> > > Your design is somewhat flawed, maybe you'd like to revise it. Getting
> > > the session through proxies from inside the entities is not something
> > > I would expect to see on a well-designed application :/
> > > Francisco A. Lozano
>
> > > On Wed, Sep 23, 2009 at 20:20, Harm Neervens <[email protected]>
> > wrote:
>
> > > > I want this because my entities are POCO, and bu that I mean real
> > > > Persistance Ignorant.
> > > > I have code in my entities that references ISessionFactory, I create a
> > > > dependancy to the NHibernate framework, and that's not what I want.
> > > > I'm building an abstraction layer between my domain model and the ORM.
> > > > In that way we can change ORM framework whenever we want (just by
> > > > adjusting some configuration settings).
> > > > Some of our customers prefer NHibernate, other Entity Framework or
> > > > NPersist.
>
> > > > When I always have proxies, then in my base class I can use code like:
>
> > > >            if (entity is INHibernateProxy)
> > > >            {
> > > >                (entity as
> > > > INHibernateProxy).HibernateLazyInitializer.Session.Load<T>..... etc
> > > >            }
>
> > > > and in case of NPersist:
>
> > > >            if (entity is IInterceptable)
> > > >            {
> > > >                (entity as
> > > > IInterceptable).Context.GetObjectById<T>....etc
> > > >            }
>
> > > > Harm.
>
> > > > Until now (I mean for almost 5 years) I used NPersist. This is an ORM
> > > > developed by Mats Helander and Roger Alsing (www.puzzleframework.com).
> > > > Because the development has stopped, and there's no active community,
> > > > I started to look at NHibernate. Another reason is that more and more
> > > > customers are asking for it.
> > > > In Entity Framework 4, there will also be POCO support, so in the
> > > > future my abstaction layer will also support EF.
> > > > Maybe it's a bit clearer now to you why I always want proxies for my
> > > > entities.
>
> > > > On Sep 23, 5:39 pm, José F. Romaniello <[email protected]> wrote:
> > > >> > When I have no proxy, I cannot cast my object to IInterceptor and so
> > I
>
> > > >> will never get to my session/context object within my entity.
>
> > > >> Well.. I have to much questions. Why do you need to do that?
> > > >> Is not a good way to get the current session by far.
>
> > > >> Inject ISessionFactory and use GetCurrentSession().. is a normal
> > approach.- Hide quoted text -
>
> > > - Show quoted text -- Hide quoted text -
>
> - Show quoted text -
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"nhusers" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to 
[email protected]
For more options, visit this group at 
http://groups.google.com/group/nhusers?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to