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
-~----------~----~----~----~------~----~------~--~---