I'm looking for some advice on how to best configure this situation.
I have the following components in an ASP MVC application.
Controllers - Transient by requirement of MVC
Services - Controllers call these to get to the business layer
Validators - Services use these to validate components. These are
expensive to create so I need them to be Singleton
Repositories - Services and Validators use these to access data
ISession - NHibernate Session configured as PerWebRequest
I'm looking at how best to configure Services and Repositories. On
the surface it seems like they could both be configured the same.
Repositories only dependency (passed in on the constructor) is
ISession. Services only dependencies (passed in on the constructor)
are Repositories. When a Service needs a Validator it gets it from
the ServiceLocator. Validators get Repositories in the constructor.
I think that because Validators are Singleton passing Transient
Repositories is problematic because the Validator will hold onto a
Repository that has a disposed ISession.
Your services and/or repositories must be configured PerWebRequest if they are using ISession. Otherwise, they'll not get recreated with different sessions (i.e. they will get created once, on the first time a controller that uses them is resolved and never recreated with the new sessions).
Since your validators use repositories to access data, they then also need to be PerWebRequest. Given the cost you mention that it takes to create them, you'll need to rethink something. One way to fix the problem is to make the repository dependency come in through a parameter to the Validator objects, so that it can be supplied dynamically. Another way would be to extract the costly part of the validator into a singleton service that is used by the validators, and allow the validators to be created PerWebRequest, with the expensive part being singletons.
As you mentioned in your message, IDisposable is a problem too, where you need things with IDisposable to have "similar" lifetimes to their users.
Another approach might be to have a "SessionProvider" or "SessionAccessor" that is a factory-like object that provides the session from the container by doing a container.Resolve<ISession>(). On the first call for a web request, this should create the session, and on later calls, it should return the same session already created. Unfortunately, you'll have to figure out how to do the container.Release() that goes with the Resolve, or else you'll have a memory leak. Hopefully someone else will give some more ideas.
On Mon, Feb 13, 2012 at 6:23 AM, Steven <reachsoftw...@gmail.com> wrote: > Hi,
> I'm looking for some advice on how to best configure this situation. > I have the following components in an ASP MVC application.
> Controllers - Transient by requirement of MVC > Services - Controllers call these to get to the business layer > Validators - Services use these to validate components. These are > expensive to create so I need them to be Singleton > Repositories - Services and Validators use these to access data > ISession - NHibernate Session configured as PerWebRequest
> I'm looking at how best to configure Services and Repositories. On > the surface it seems like they could both be configured the same. > Repositories only dependency (passed in on the constructor) is > ISession. Services only dependencies (passed in on the constructor) > are Repositories. When a Service needs a Validator it gets it from > the ServiceLocator. Validators get Repositories in the constructor. > I think that because Validators are Singleton passing Transient > Repositories is problematic because the Validator will hold onto a > Repository that has a disposed ISession.
> Any help here would be greatly appreciated.
> -- > You received this message because you are subscribed to the Google Groups > "Castle Project Development List" group. > To post to this group, send email to castle-project-devel@googlegroups.com > . > To unsubscribe from this group, send email to > castle-project-devel+unsubscribe@googlegroups.com. > For more options, visit this group at > http://groups.google.com/group/castle-project-devel?hl=en.
> Another approach might be to have a "SessionProvider" or "SessionAccessor"
> that is a factory-like object that provides the session from the container
> by doing a container.Resolve<ISession>(). On the first call for a web
> request, this should create the session, and on later calls, it should
> return the same session already created. Unfortunately, you'll have to
> figure out how to do the container.Release() that goes with the Resolve, or
> else you'll have a memory leak. Hopefully someone else will give some more
> ideas.
Why not put the ISessionFactory in the container, and then create the
ISession at the start of the web request. Any code that needs access
to the current ISession can call GetCurrentSession() on the session
factory.
Isn't this pretty much how castle always used to work?
Anyways, if there's something I regret is these customs lifestyle managers. We should be good with singleton/transient for 99.9% of situations. Well, maybe on Windsor 4...
On Tue, Feb 14, 2012 at 8:23 AM, Jordan <augustusgor...@yahoo.co.uk> wrote: >> Another approach might be to have a "SessionProvider" or "SessionAccessor" >> that is a factory-like object that provides the session from the container >> by doing a container.Resolve<ISession>(). On the first call for a web >> request, this should create the session, and on later calls, it should >> return the same session already created. Unfortunately, you'll have to >> figure out how to do the container.Release() that goes with the Resolve, or >> else you'll have a memory leak. Hopefully someone else will give some more >> ideas.
> Why not put the ISessionFactory in the container, and then create the > ISession at the start of the web request. Any code that needs access > to the current ISession can call GetCurrentSession() on the session > factory.
> Isn't this pretty much how castle always used to work?
> regards, > Jordan.
> -- > You received this message because you are subscribed to the Google Groups "Castle Project Development List" group. > To post to this group, send email to castle-project-devel@googlegroups.com. > To unsubscribe from this group, send email to castle-project-devel+unsubscribe@googlegroups.com. > For more options, visit this group at http://groups.google.com/group/castle-project-devel?hl=en.
I agree. We don't use "PerWebRequest" for anything. Just transient or singelton. We also just use auto factories in the cases where we need to get access to a stateful object that needs dependencies auto resolved. It took a bit of getting used to using the auto factories, since some bits of them are a tiny bit annoying, but now we've had pretty good luck.
On Tue, Feb 14, 2012 at 11:39 AM, hammett <hamm...@gmail.com> wrote: > I'd prefer that as well.
> Anyways, if there's something I regret is these customs lifestyle > managers. We should be good with singleton/transient for 99.9% of > situations. Well, maybe on Windsor 4...
> On Tue, Feb 14, 2012 at 8:23 AM, Jordan <augustusgor...@yahoo.co.uk> > wrote: > >> Another approach might be to have a "SessionProvider" or > "SessionAccessor" > >> that is a factory-like object that provides the session from the > container > >> by doing a container.Resolve<ISession>(). On the first call for a web > >> request, this should create the session, and on later calls, it should > >> return the same session already created. Unfortunately, you'll have to > >> figure out how to do the container.Release() that goes with the > Resolve, or > >> else you'll have a memory leak. Hopefully someone else will give some > more > >> ideas.
> > Why not put the ISessionFactory in the container, and then create the > > ISession at the start of the web request. Any code that needs access > > to the current ISession can call GetCurrentSession() on the session > > factory.
> > Isn't this pretty much how castle always used to work?
> > regards, > > Jordan.
> > -- > > You received this message because you are subscribed to the Google > Groups "Castle Project Development List" group. > > To post to this group, send email to > castle-project-devel@googlegroups.com. > > To unsubscribe from this group, send email to > castle-project-devel+unsubscribe@googlegroups.com. > > For more options, visit this group at > http://groups.google.com/group/castle-project-devel?hl=en.
> -- > You received this message because you are subscribed to the Google Groups > "Castle Project Development List" group. > To post to this group, send email to castle-project-devel@googlegroups.com > . > To unsubscribe from this group, send email to > castle-project-devel+unsubscribe@googlegroups.com. > For more options, visit this group at > http://groups.google.com/group/castle-project-devel?hl=en.