You can also use IoC with NH by implementing your own BytecodeProvider
and ReflectionOptimizer. this isn't required, but can be helpful if
dependency injection is required.
I believe there is a Nhibernate Facility as part of the Castle source
code which handles most/all of the first paragraph above. Because I
use the trunk of both NH and Castle I have found it's easier to simply
roll my own facility for each project rather than manage all the
project dependencies each time I build from the trunk.
On Jan 21, 7:34 am, Sheri <sheri.soli...@gmail.com> wrote:
> Hello!
>
> Does anyone know any god link/documentation to using Castle (Kernel/
> Facilities/Windsor) in NHibernate 2.1.
>
> Thanks in advance
> /Sheri
--
You received this message because you are subscribed to the Google Groups "nhusers" group.
To post to this group, send email to nhu...@googlegroups.com.
To unsubscribe from this group, send email to nhusers+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/nhusers?hl=en.
I am almost newbie and I need more details. like how to configure the
configuration file (web.config) with castle ...
Hope somebody can help!
Regards
Sheri
public NhibernateFacility : AbstractFacility
{
public override void Init()
{
var configuration = new Configuration().Configure();
var factory = configuration.BuildSessionFactory();
Kernel.AddComponentInstance("nhibernate_configuration",
configuration);
Kernel.AddComponentInstance("session_factory", );
Kernel.Resolvers.Add(NhibernateSessionResolver(Kernel));
//I could also use the factory method to resolve the session, but
that can cause a memory leak if i don't also implement
//a custom lifecyle for it. It's easier just to resolve the session
with sub dependency resolver.
//It's also easier to test in isolation.
}
}
public NhibernateSessionResolver : ISubDependencyResolver
{
private readonly IKernel kernel;
public NhibernateSessionResolver(IKernel kernel)
{
this.kernel = kernel;
}
public bool Resolve(CreationContext context, ISubDependencyResolver
contextHandlerResolver, ComponentModel model, DependencyModel
dependency)
{
return kernel.Resolve<ISessionFactory>().GetCurrentSession();
}
public bool CanResolve(CreationContext context,
ISubDependencyResolver contextHandlerResolver, ComponentModel model,
DependencyModel dependency)
{
return typeof(ISession).IsAssignableFrom(dependency.TargetType);
}
}
new Configuration().Configure() will automatically load the
hibernate.config file from the root directory of the project. part of
this configuration will be a property defining the
CurrentSessionContext web, thread, map, etc. the best choice for this
will depend on where you are using this configuration. With this is
place I can now inject a session into other objects.
public class Foo
{
private readonly ISession session;
public Foo(ISession session)
{
this.session = session;
}
}
I can then register Foo into the container as well with a transient
lifestyle and all will be resolved for me automatically.
The next piece to consider is managing when to open/close the session.
I work with web applications and use an HttpModule to manage the
session.
public class SessionScope : IHttpModule
{
public void Init(HttpApplication context)
{
context.BeginRequest += OpenSession;
context.EndRequest += CloseSession;
}
private void OpenSession(object sender, EventArgs e)
{
var factory = WindsorContainerAccessorUtil.ObtainConatiner
().Resolve<ISessionFactory>();
CurrentSessionContext.Bind(factory.OpenSession());
}
private void CloseSession(object sender, EventArgs e)
{
var factory = WindsorContainerAccessorUtil.ObtainConatiner
().Resolve<ISessionFactory>();
if (!CurrentSessionContext.HasBind(factory)) return;
var session = CurrentSessionContext.Unbind(factory);
session.Dispose();;
}
}
and I register this module in web.config. then I need to manage my
transactions. I use Monorail as my web framework and create a filter
to manage this.
public class TransactionFilter : Filter
{
private readonly ISession session;
public TransactionFilter(ISession session)
{
this.session = session;
}
protected override bool OnBeforeAction(IEngineContext context,
IController controller, IControllerContext, controllerContext)
{
session.BeginTransaction();
return base.OnBeforeTransaction();
}
protected override void OnAfterAction(IEngineContext context,
IController controller, IControllerContext, controllerContext)
{
using(session.Transaction)
{
if(context.LastException == null)
{
session.Transaction.Commit;
}
else
{
session.Transaction.Rollback();
}
}
}
}
Each Controller/ViewComponent action then becomes it's own unit of
work. This drives the design of the workflow within each action.
I then register the TransactionFilter in the Kernel as transient and
place a FilterAttribute for the TransactionFilter on any controller
that requires is. If I don't need a transaction for a specific action
i can apply the SkipFilter attribute to that action.
On Jan 25, 5:03 am, Sheri <sheri.soli...@gmail.com> wrote:
> Hi!
>
> How can I register the sessionfactory in IKernel?
>
> API in the documentation is not enough for me.
>
> I have a class as following:
>
> ______________________________
> using System.Web;
> using NHibernate;
> using NHibernate.Cfg;
>
> namespace WebMonitorUpdate.SQLServerServices
> {
> public sealed class DBConnectionService
> {
> static readonly DBConnectionService instance = new
> DBConnectionService();
> private const string CurrentSessionKey = "_session";
> private static readonly ISessionFactory sessionFactory;
>
> static DBConnectionService()
> {
> if(DBConnectionService.sessionFactory == null)
> sessionFactory = new Configuration().Configure
> ().BuildSessionFactory();
> }
>
> DBConnectionService()
> {
> }
>
> public static DBConnectionService Instance
> {
> get
> {
> return instance;
> }
> }
>
> public ISession OpenSession()
> {
> HttpContext context = HttpContext.Current;
> ISession currentSession = context.Items[CurrentSessionKey]
> as ISession;
>
> if (currentSession == null)
> {
> currentSession = sessionFactory.OpenSession();
> context.Items[CurrentSessionKey] = currentSession;
> }
>
> return currentSession;
> }
>
> public void CloseSession()
> {
> HttpContext context = HttpContext.Current;
> if (context == null) return;
> ISession currentSession = context.Items[CurrentSessionKey]
> as ISession;
>
> if (currentSession == null)
> {
> // No current session
> return;
> }
>
> currentSession.Close();
> context.Items.Remove(CurrentSessionKey);
> }
>
> public void CloseSessionFactory()
> {
> if (sessionFactory != null)
> {
> sessionFactory.Close();
> }
> }
> }}
>
> _________________________________
>
> And I will register this class in the IKernel. could I do this? how?
> if no, what do I missing here?!
>
> Thanks in advance
> Sheri
>
> On 21 Jan, 19:42, Jason Meckley <jasonmeck...@gmail.com> wrote:
>
> > there are 2 configurations in this scenario. Nhibernate andCastle.
> > Nhibernate configuration is very easy to figure out using the xml
> > schema docs.Castle, on the other hand is very open ended. the documentation (found
> > herehttp://www.castleproject.org/container/documentation/v21/index.html)
> > is the best place to start. because each facility/component can be
> > configured uniquely there is no xml schema. however the amount ofCastlexml configure is greatly reduced with the fluent registration
> > API.
>
> > On Jan 21, 10:33 am, Sheri <sheri.soli...@gmail.com> wrote:
>
> > > Thanks for your answer Jason!
>
> > > I am almost newbie and I need more details. like how to configure the
> > > configuration file (web.config) withcastle...
>
> > > Hope somebody can help!
>
> > > Regards
> > > Sheri
>
> > > On 21 Jan, 15:21, Jason Meckley <jasonmeck...@gmail.com> wrote:
>
> > > > the 2 frameworks solve unique problems. they can be used together, but
> > > > how that is done is really up to you. the common approach is to
> > > > register the configuration and session factory as singletons in the
> > > > container. then resolve the session from the factory by implementing
> > > > ISubDependencyResolver. to resolve the same session for a given scope
> > > > use the ISessionFactory.GetCurrentSession() method.
> > > > defining the session and transaction boundaries is up to you. for web
> > > > applications most use a Session per Request and implement a
> > > > Transaction Filter.
>
> > > > You can also use IoC with NH by implementing your own BytecodeProvider
> > > > and ReflectionOptimizer. this isn't required, but can be helpful if
> > > > dependency injection is required.
>
> > > > I believe there is a Nhibernate Facility as part of theCastlesource
> > > > code which handles most/all of the first paragraph above. Because I
> > > > use the trunk of both NH andCastleI have found it's easier to simply
((just a point to them who would like to use NH 2.1.2.4000 and latest
Castle versions, NHibernate.ByteCode.Castle source code should be
built by the latest version of Castle.Core and Castle.DynamicProxy2.))
I use IHttpModule to open/close session but I get "Session Closed"
error.
1. web.config: I have current_session_context_class = web & <add
name="SessionScope" type="MyPackage.Helper.SessionScope, MyPackage"/>
in my httpModule section
2. I have a daoFactory which is registered in container. this
daoFactory initialize all my DAOs. (But I do not have registered my
dao in the container directly. DAO classes are for CRUD operation)
3. I have some services classes which has some dao as object for other
process with retrieved data from DAOs. In these services classes I
have initialized each dao through daofactory
4. All my daos is inserted in castle section of web.config
I do not know why I get "session closed error". The only thing I can
guess is registration in container which I have some trouble to
understand.
SessionScope (that implements IHttpModule) should retrieve and close
session byself? or?
Thanks for any help
Regards
Sheri
controller > dao > session. all must be transient
controller > service
> dao > session. controller and dao must be transient,
service can be a singleton, if necessary.
by default component lifestyles are "undefined" which defaults to
singletons.
On Jan 26, 3:54 pm, Sheri <sheri.soli...@gmail.com> wrote:
> ______________________
> By the way the error message is (sorry for swedish language in the
> message):
>
> System.ObjectDisposedException was unhandled by user code
> Message="Session is closed!\r\nObjektnamn: ISession."
> Source="NHibernate"
> ObjectName="ISession"
> StackTrace:
> vid NHibernate.Impl.AbstractSessionImpl.ErrorIfClosed()
> vid
> NHibernate.Impl.AbstractSessionImpl.CheckAndUpdateSessionStatus()
> vid NHibernate.Impl.SessionImpl.CreateCriteria(Type
> persistentClass, String alias)
> vid
> WebMonitorUpdate.Models.NHDataAccessObjects.OnlineSystemDAO.findByUsername
> (String username) i C:\Projects\WebMonitorUpdate\WebMonitorUpdate
> \Models\NHDataAccessObjects\OnlineSystemDAO.cs:rad 55
> vid
> WebMonitorUpdate.SQLServerServices.OnlineSystemService.getCustomerInfoByName
> (String username) i C:\Projects\WebMonitorUpdate\WebMonitorUpdate
> \SQLServerServices\OnlineSystemService.cs:rad 33
> vid
> WebMonitorUpdate.MembershipServicesImpl.SQLServerMembershipProvider.ValidateUser
> (String usernameAndSystemId, String password) i C:\Projects
> \WebMonitorUpdate\WebMonitorUpdate\MembershipServicesImpl
> \SQLServerMembershipProvider.cs:rad 139
> vid
> WebMonitorUpdate.MembershipServicesImpl.AccountMembershipService.ValidateUser
> (String systemId, String userName, String password) i C:\Projects
> \WebMonitorUpdate\WebMonitorUpdate\MembershipServicesImpl
> \AccountMembershipService.cs:rad 32
> vid WebMonitorUpdate.Validators.AccountValidators.ValidateLogOn
> (String systemId, String userName, String password, IMembershipService
> membershipService, ModelStateDictionary modelState) i C:\Projects
> \WebMonitorUpdate\WebMonitorUpdate\Validators\AccountValidators.cs:rad
> 50
> vid WebMonitorUpdate.Controllers.AccountController.LogOn(String
> systemId, String userName, String password, Boolean rememberMe, String
> returnUrl) i C:\Projects\WebMonitorUpdate\WebMonitorUpdate\Controllers
> \AccountController.cs:rad 70
> vid lambda_method(ExecutionScope , ControllerBase , Object[] )
> vid System.Web.Mvc.ActionMethodDispatcher.Execute
> (ControllerBase controller, Object[] parameters)
> vid System.Web.Mvc.ReflectedActionDescriptor.Execute
> (ControllerContext controllerContext, IDictionary`2 parameters)
> vid System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod
> (ControllerContext controllerContext, ActionDescriptor
> actionDescriptor, IDictionary`2 parameters)
> vid
> System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClassa.<InvokeActionMethodWithFilters>b__7
> ()
> vid
> System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter
> (IActionFilter filter, ActionExecutingContext preContext, Func`1
> continuation)
> vid
> System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClassa.<>c__DisplayClassc.<InvokeActionMethodWithFilters>b__9
> ()
> vid
> System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodWithFilters
> (ControllerContext controllerContext, IList`1 filters,
> ActionDescriptor actionDescriptor, IDictionary`2 parameters)
> vid System.Web.Mvc.ControllerActionInvoker.InvokeAction
> (ControllerContext controllerContext, String actionName)
> vid System.Web.Mvc.Controller.ExecuteCore()
> vid System.Web.Mvc.ControllerBase.Execute(RequestContext
> requestContext)
> vid
> System.Web.Mvc.ControllerBase.System.Web.Mvc.IController.Execute
> (RequestContext requestContext)
> vid System.Web.Mvc.MvcHandler.ProcessRequest(HttpContextBase
> httpContext)
> vid System.Web.Mvc.MvcHandler.ProcessRequest(HttpContext
> httpContext)
> vid
> System.Web.Mvc.MvcHandler.System.Web.IHttpHandler.ProcessRequest
> (HttpContext httpContext)
> vid System.Web.Mvc.MvcHttpHandler.VerifyAndProcessRequest
> (IHttpHandler httpHandler, HttpContextBase httpContext)
> vid System.Web.Routing.UrlRoutingHandler.ProcessRequest
> (HttpContextBase httpContext)
> vid System.Web.Routing.UrlRoutingHandler.ProcessRequest
> (HttpContext httpContext)
> vid
> System.Web.Routing.UrlRoutingHandler.System.Web.IHttpHandler.ProcessRequest
> (HttpContext context)
> vid WebMonitorUpdate._Default.Page_Load(Object sender,
> EventArgs e) i C:\Projects\WebMonitorUpdate\WebMonitorUpdate
> \Default.aspx.cs:rad 18
> vid System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr
> fp, Object o, Object t, EventArgs e)
> vid System.Web.Util.CalliEventHandlerDelegateProxy.Callback
> (Object sender, EventArgs e)
> vid System.Web.UI.Control.OnLoad(EventArgs e)
> vid System.Web.UI.Control.LoadRecursive()
> vid System.Web.UI.Page.ProcessRequestMain(Boolean
> includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
> InnerException:
>
> ______________________
> ...
>
> read more »
I haven't used the MembershipProvider explicitly. The apps I create
are intranet apps on a Windows Domain. We utlize windows
authentication, so I'm haven't had to explicitly control the login
process.
can you post the relevant code for the provider (and associated
objects)? We should be able to get this to work.
On Jan 27, 9:00 am, Sheri <sheri.soli...@gmail.com> wrote:
> Jason, thanks again for your quick answer!
>
> All of component who injects session are transient.
> The only thing that I can guess is "MembershipProvider" in ASP .NET
> MVC. I cannot register it as a component. and since I user one of my
> services in my costumized provider I should register this one as a
> transient component too but I cannot do.
>
> Is it true? what can I use instead of OoTB "Membership Provider" in
> ASP .NET MVC 1.0?
>
> /Sheri
>
> On 26 Jan, 22:32, Jason Meckley <jasonmeck...@gmail.com> wrote:> if you are injecting the session into a service, the service must be
> > > System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClassa.<InvokeActionMeth odWithFilters>b__7
> > > ()
> > > vid
> > > System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter
> > > (IActionFilter filter, ActionExecutingContext preContext, Func`1
> > > continuation)
> > > vid
> > > System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClassa.<>c__DisplayClass c.<InvokeActionMethodWithFilters>b__9
> > > > > context.BeginRequest...
>
> > läs mer »
I have followed all advices. Everything works fine and SessionScope
seems to be worked fine. but I still have "Session Closed!" error. I
get this error exactly when the logined page will appear after login!
The reason that I got through debug is "Membership Provider". this
OoTB approach need default constructor, and DI needs another
constructor for DI objects, the problem begins here. Membership
Provider initialized (default ctor) by ASP .NET MVC oOTB membership
approach and when the user will log in Membership provider initializes
via DI (ctor with DI objects) again that I guess the older session is
no more active.
tired of these conflicts and lack of my knowledge to solve it :-S
Any idea?
Thanks once again and again
/Sheri
> > > > > > ...
>
> läs mer »
I use Monorail which ties in very nicely with Windsor, so i take for
granted that Filters/Controller/etc are resolved from the Kernel.
There is a project called MvcContrib which is primarly maintained by
HeadSpring. If you are not familar with this project I would highly
recommend it. It picks up with MS MVC stops.
If there isn't a way to change how the membership provider is created.
you will need to find a hook to inject the dependencies via
properties. it would look something like
var provider = GetProviderByDefaultCtor.
provider.Dependency = kernel.Resolve<Dependency>();
//then return or use the provider.
Not as clean, but it gets the dependencies into the provider.
> ...
>
> read more »
If you have some example for your description below I am very thankful
otherwise I am still very thankful for all that time you spent to help
me.
Best Regards
Sheri
P.S. How long does it take to be a capable developer like you?!
> ...
>
> läs mer »
"How long does it take to be a capable developer like you?! "
I have been a developer for ~9 years. I didn't have a clue what i was
doing for the first 5. the turning point for me was *nothin' but .net*
(http://www.jpboodhoo.com/training.oo). Up until then I had no idea
what OOP really was. after than projects like Castle and Nhibernate
made more sense and i could understand what was happening when I
looked at the code. www.ayende.com, www.codebetter.com and www.lostechies.com
also helped me progress.
> ...
>
> read more »
I would make 1 tiny change to the transaction code (assuming you can
resolve the session from the container directly.)
using (var tx = WindsorContainerAccessorUtil
.ObtainContainer()
.Resolve<ISession>()
.BeginTransaction())
{
try
{
...
tx.Commit();
}
catch
{
tx.Rollback();
throw;
}
}
Another approach to managing the session would be implementing an
Interceptor (similar to filters) IInterceptor is part of Castle and
can be applied to any component (not a sealed class and virtual
members) registered in the container. with this you could do something
like
class TransactionInterceptor:IInterceptor
{
private ISession session;
public TransactionInterceptor(ISession session)
{
this.session = session;
}
public void Intercept(IInvocation invocation)
{
if(session.Transaction.IsActive)
{
invocation.Proceed();
return;
}
using(var tx = session .BeginTransaction())
{
try
{
invocation.Proceed();
tx.Commit();
}
catch
{
tx.Rollback();
throw;
}
}
}
}
there is the issue that interceptors will intercept all calls to
public/protected virtual memebers and you may not want a transaction
on every one. For that you can Implement IOnBehalfOf (or IAwareOf, I
forget exactly) which allows you to selectively choose when the
invocation is intercepted. I'm not 100% sure how to use/configure it.
The only implementation I have seen was on a blog post by Ayende way
back in the day dealing with query caching and generic repositories.
On Jan 29, 5:21 am, Sheri <sheri.soli...@gmail.com> wrote:
> Thanks Jason
>
> I have had an overridden controller factory almost like yours here. It
> is solved now.
>
> The only thing that I do not use is Filter for managing transaction.
> The reason is I use ASP .NET MVC Controller which I cannot use Filter
> in Monorail (due to confliction).
>
> Due to lack of time I am satisfied to use:
>
> using (ITransaction tx = WindsorContainerAccessorUtil.ObtainContainer
> ().Resolve<ISessionFactory>().GetCurrentSession().BeginTransaction())
> {
> ...
>
> }
>
> Thanks once again
> /Sheri
> ...
>
> read more »
--
You received this message because you are subscribed to the Google Groups "nhusers" group.
To post to this group, send email to nhu...@googlegroups.com.
To unsubscribe from this group, send email to nhusers+unsubscribe@googlegroups.com.
I hope I am not hijacking Sheri's thread but I wanted to ask some
questions about your approach with registering NH in Windsor. I am
very much a Noob to NH and Windsor, being a very old school developer
find it hard to find my way around. Trying this code in small test
project using NH 2.1 and Castle 2.0 I get some errors which I presume
relate to version. Specifically AbstractFacility method Init which is
protected, I wondering what the significance of this is if anything,
and also method Kernel.MethodResolvers.Add I cannot see, looking at
IKernel I can see several AddFacility method, are they the same?
My objective is to convert/rewrite old VB6 application mostly Winforms
and want to use IOC ORM techniques and also develop in 3 tiers with
out any dependancy between the layers. Where I am at is looking at
long conversation pattern DAO's and repositories and how to inject
current session.
Thanks
It sounds like you are not familiar with the basic and advanced
features of Windsor. This is key in integrating NH with the kernel. I
would spike examples of using NH and Windsor (Kernel) independent of
one another. Questions about how to use the Kernel can be directed to
http://groups.google.com/group/castle-project-users.
Moving forward, please start a new thread in this forum for NH
specific questions.