I have been trying for three days to figure out this NHibernatefacility thing with Castle and wcf and it's really getting frustrating.
After solving a good dozen of errors, i have come to this one which seems pretty obvious but i can't solve.
This is my global.asax's Application_Start
container.AddFacility<AutoTxFacility>();
container.Register(Component.For<INHibernateInstaller>().ImplementedBy<NHibernateInstaller>());
container.AddFacility<NHibernateFacility>();
container.AddFacility<WcfFacility>();
container.Register(
Component.For<IAuthService>().ImplementedBy<AuthService>().LifestylePerWcfOperation(),
Component.For<IUserRepository>().ImplementedBy<UserRepository>().LifestylePerWcfOperation(),
Component.For<IActionWebService>().ImplementedBy<ActionWebService>().Named("ActionWebService").LifestylePerWcfOperation(),
Component.For<ISession>().LifeStyle.PerWcfOperation().UsingFactoryMethod(x => container.Resolve<ISessionManager>().OpenSession()));
This works for the first request. After that, it comes up with this error.
The factory was disposed and can no longer be used. Object name: 'this'.
the error is happening in my userrepository in this line
[Transaction]
public virtual User GetUserByCredentials(string email, string password)
{
using (var tx = session())
{
return tx.QueryOver<User>().Where(x => x.Email == email && x.Password == password).SingleOrDefault();
}
}
I am having a feeling this has to do with the LIfestyle. I have tried multiple combinations but unsuccessful. I don't know what to do at this point. I got into this Castle thing with all the facilities (that are supposed to make life easier) and it's really complicated due to the lack of documentation. I haven't been able to find a descent guide to implement all of this together, not to mention something that is not 4 years old.
Help Please!
Sorry for not finding this question previously.
The most likely reason you're getting this error message is that you are re-registering the ISession. The point of the facility is to provide that support for you.
I also read in your comment that you have set the ISession to singleton. That should never ever be done, because any single fault on it an you will crash and burn and you'll have to throw away the full container (which most often is the composition root of the application, so you have to reboot the application).
The point of the facility is to give you AOP-based transactions, and then you need to have your transactions as close to the GUI or command layer as possible. Child operation, such as reading should not be wrapped in singular transactions with [Transaction]
because they do not denote the transactional boundary for your operation.
Instead, look at your surface API and see where you have methods being called that are supposed to run with ACID; this is where you put the attributes.
In your case, it seems that your transactional boundaries are around the WCF calls. What you'd need to do is to replace the lifestyle that the ISession is registered with.
If you have a look at the c'tor for NHibernateFacility, you'll find an option to pass transient lifestyle; if all of your components depending on ISession are transient you'll be good to go with Transient lifestyle on ISession, because it is guaranteed to only live for as long as the object taken from the composition root/container lives.
The 'real' fix is to extend the facility, from my github, with an enum in the c'tor taking a PerWCFOperation value, and having the facility register ISessionManager and Func with those, similar to how it does with the three existing lifestyles.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With