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.
Related
In order to get early-warning of a slow or potentially slow areas, I'd like to have an Interceptor for NHibernate that can act as a performance monitor, so that any database operation that takes more than a given time raises an event and (importantly) a full stacktrace into the application's logs.
Interceptors seemed to be a good window into this. However, having experimented, there doesn't seem to be anyway to catch a "just-back-from-SQL" event:
OnPreFlush and OnPostFlush work on full batches where writes are involved, but aren't invoked on read events.
OnPrepareStatement() seems to be the best to put start measuring, but to stop?
For read events, OnLoad might be the place to stop the clock, but it's called once-per-entity returned - how do I know when I've got to the end of all entities?
For write events, I can't see any post-SQL event (other than those that work on the entire batch - OnPostFlush and OnAfterTransaction; I get the impression OnSave, OnFlushDirty, etc are called before the actual database call occurs - happy to be corrected though).
From what I can tell, documentation is heavily lacking on exactly what the pipeline order is with NHibernate's interaction with the database, and thus when in that pipeline different events and interceptor calls are called in relation to the actual SQL execution itself.
This is something that needs to be permanently available, sitting in the background, pretty much that requires no human intervention except when slow queries are detected. It also needs to run headless on a large farm of servers, so interactive tools such as NHibernate Profiler are out: it's literally something that we can enable and forget about, letting it log as and when appropriate.
Is there anything I have missed or misunderstood?
I had a similar problem. I wanted measure and log all queries that goes through NHibernate.
What I did is I wrote a custom batching factory (in this case I work with oracle) but you can apply the same technique to any db:
1-) Implement batcher factory, (in this case I am extending existing factory)
public class OracleLoggingBatchingBatcherFactory : OracleDataClientBatchingBatcherFactory
{
public override IBatcher CreateBatcher(ConnectionManager connectionManager, IInterceptor interceptor)
{
return new OracleLoggingBatchingBatcher(connectionManager, interceptor);
}
}
2-) Implement the Batcher itself (in this case I am extending existing batcher). Make sure you inherit IBatcher again since we want our new methods to be called
public class OracleLoggingBatchingBatcher : OracleDataClientBatchingBatcher, IBatcher
{
.... // here override ExecuteNonQuery, DoExecuteBatch and ExecuteReader.
//You can do all kind of intercepting, logging or measuring here
//If they are not overrideable just implement them and use "new" keyword if necessary
//since we inherit IBatcher explicitly it will work polymorphically.
//Make sure you call base implementation too or re-implement the method from scratch
}
3-) Register the factory via NHibernate config:
<property name="adonet.factory_class">OracleLoggingBatchingBatcherFactory, MyAssembly</property>
I'm using StructureMap and I've configured ISession with HybridHttpOrLocalThreadStorage life cycle. New session is created and injected into controllers on per request basis.
Now, the question I have is about disposal. I've read number of articles presenting number of different approaches. Some people were doing it in controllers, some in repositories, some in http modules and others did it in Application_EndRequest() handler. Critique ranged from SRP violations to 'the one creating an object should be responsible for its disposal' to name a few.
So the bottom line is that:
common approach was to manually dispose these sessions - why? I have already configured my container to manage particular object's life cycle. Shouldn't it (i.e. IoC) manage it for me?
out of options available for disposal is handling it in Application_EndRequest() "the best" way of going about it?
For example, this article explains in length one available approach but the article itself is over 2.5 years old. Perhaps new version of StructureMap makes most of that implementation obsolete?
If you are using RavenDB .net client you will be using DocumentStore and DocumentSession. Both of these object do a fair amount of work in the background; local caching to mention one thing. Just to keep things clean and efficient, each session should call session.dispose() when the work is done. documentStore.Dispose() should be called when the application ends.
OK, I want to make sure I cover my situation and everything I've tried thoroughly. I'm pretty sure what I need/want can be done, but I haven't quite found the perfect combination for success.
I'm utilizing Entity Framework 4 RTM and its POCO support. I'm looking to query for an entity (Config) that contains a many-to-many relationship with another entity (App). I turn off lazy loading and disable proxy creation for the context and explicitly load the navigation property (either through .Include() or .LoadProperty()). However, when the navigation property is loaded (that is, Apps is loaded for a given Config), the App objects that were loaded already contain references to the Configs that have been brought to memory. This creates a circular reference.
Now I know the DataContractSerializer that WCF uses can handle circular references, by setting the preserveObjectReferences parameter to true. I've tried this with a couple of different attribute implementations I've found online. It is needed to prevent the "the object graph contains circular references and cannot be serialized" error. However, it doesn't prevent the serialization of the entire graph, back and forth between Config and App.
If I invoke it via WcfTestClient.exe, I get a stackoverflow (ha!) exception from the client and I'm hosed. I get different results from different invocation environments (C# unit test with a local reference to the web service appears to work ok though I still can drill back and forth between Configs and Apps endlessly, but calling it from a coldfusion environment only returns the first Config in the list and errors out on the others.) My main goal is to have a serialized representation of the graph I explicitly load from EF (ie: list of Configs, each with their Apps, but no App back to Config navigation.)
NOTE: I've also tried using the ProxyDataContractResolver technique and keeping the proxy creation enabled from my context. This blows up complaining about unknown types encountered. I read that the ProxyDataContractResolver didn't fully work in Beta2, but should work in RTM.
For some reference, here is roughly how I'm querying the data in the service:
var repo = BootStrapper.AppCtx["AppMeta.ConfigRepository"] as IRepository<Config>;
repo.DisableLazyLoading();
repo.DisableProxyCreation();
//var temp2 = repo.Include(cfg => cfg.Apps).Where(cfg => cfg.Environment.Equals(environment)).ToArray();
var temp2 = repo.FindAll(cfg => cfg.Environment.Equals(environment)).ToArray();
foreach (var cfg in temp2)
{
repo.LoadProperty(cfg, c => c.Apps);
}
return temp2;
I think the crux of my problem is when loading up navigation properties for POCO objects from Entity Framework 4, it prepopulates navigation properties for objects already in memory. This in turn hoses up the WCF serialization, despite every effort made to properly handle circular references.
I know it's a lot of information, but it's really standing in my way of going forward with EF4/POCO in our system. I've found several articles and blogs touching upon these subjects, but for the life of me, I cannot resolve this issue. Feel free to simply ask questions and help me brainstorm this situation.
PS: For the sake of being thorough, I am injecting the WCF services using the HEAD build of Spring.NET for the fix to Spring.ServiceModel.Activation.ServiceHostFactory. However I don't think this is the source of the problem.
EDIT: The ProxyDataContractResolver class works correctly if I don't have the circular references. (i.e.: I make the setter of App.Configs to be private, which prevents serialization of the property.) It blows up, it appears, when it hits Configs via the App object -- they don't seem to be recognized as the same type as the top level Configs.
EDIT2: It appears that either EF or WCF doesn't recognize that the entities are indeed equal. i.e.: 'Config' is the same as a particular 'Config.Apps[x].Configs[y]'. The entity keys are properly set in the CSDL for each model and I've overridden the Equals() function to compare entities based on their 'Id' property. This fits the symptoms as no circular reference error is thrown, yet it is indeed a circular reference (and blows up WcfTestClient.exe) AND the ProxyDataContractResolver blows up when it hits the 'Config.Apps[x].Configs[y]' level of Configs. (It doesn't know how to map a Config proxy. The ProxyDataContractResolver works otherwise. It's like it knows how to handle the initial round of entities, but the second level it considers as different entities.)
Wow, I can be wordy. Sorry folks!
You might want to check out my blog post on this specific scenario - please email me if it doesn't help fix your current predicament! I've included a sample solution as well.
Please drop me some feedback either way, I'd really like to hear from more people on this particular issue - especially with the implementation problems on the client end of things.
hrmm, I may not have fully understood the issue, but everytime I run into circular references with WCF the answer is to change [DataContract] on the offending classes to [DataContract(IsReference = true)].
This is a huge help compared to all the drek of messing with the contract resolvers that was needed pre WCF 3.5 SP1.
Hope this helps.
Faced the same issue today and used Value Injecter to solve it. It's as simple as:
var dynamicProxyMember = _repository.FindOne<Member>(m=>m.Id = 1);
var member = new Member().InjectFrom(dynamicProxyMember) as Member;
We couldnt afford disabling ProxyCreation
Try setting myContext.ContextOptions.ProxyCreationEnabled = false;
If the problem is solved (like mine) then you've not followed the steps mentioned in: http://msdn.microsoft.com/en-us/library/ee705457.aspx
This solved the problem for me.
You can use the ApplyDataContractResolverAttribute and a ProxyDataContractResolver along with the CyclicReferencesAwareAttribute. At first this produces error like this one - as if there is no DataContractResolver specified at all:
Type 'System.Data.Entity.DynamicProxies.Whatever_E6......A9' with data contract name 'Whatever_E6......A9:http://schemas.datacontract.org/2004/07/System.Data.Entity.DynamicProxies' is not expected. Consider using a DataContractResolver or add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer.
It will work with one simple change.
In the ApplyCyclicDataContractSerializerOperationBehavior, the constructors for the DataContractSerializer must also pass in the DataContractResolver. This is left out of all the versions I have seen online.
Example:
public class ApplyCyclicDataContractSerializerOperationBehavior : DataContractSerializerOperationBehavior
{
private readonly Int32 _maxItemsInObjectGraph;
private readonly bool _ignoreExtensionDataObject;
public ApplyCyclicDataContractSerializerOperationBehavior(OperationDescription operationDescription, Int32 maxItemsInObjectGraph, bool ignoreExtensionDataObject, bool preserveObjectReferences)
: base(operationDescription)
{
_maxItemsInObjectGraph = maxItemsInObjectGraph;
_ignoreExtensionDataObject = ignoreExtensionDataObject;
}
public override XmlObjectSerializer CreateSerializer(Type type, String name, String ns, IList<Type> knownTypes)
{
return new DataContractSerializer(type, name, ns, knownTypes,
_maxItemsInObjectGraph,
_ignoreExtensionDataObject,
true,
null /*dataContractSurrogate*/,
DataContractResolver); // <-----------------------------
}
public override XmlObjectSerializer CreateSerializer(Type type, XmlDictionaryString name, XmlDictionaryString ns, IList<Type> knownTypes)
{
return new DataContractSerializer(type, name, ns, knownTypes,
_maxItemsInObjectGraph,
_ignoreExtensionDataObject,
true,
null /*dataContractSurrogate*/,
DataContractResolver); // <-----------------------------
}
}
Is it ok from your real-world-experience to define service contract with one method which will accept some object as a form of request and return some other object as a result of that request. What I mean is instead of having method for creating, deleting, editing and searching customers I would have these activities encapsulated within DataContracts and what service would do after receiving such DataContract would be take some action accordingly. But service interface would be simple as that:
interface ISomeService
{
IMessageResult Process(IMessageRequest msg);
}
So IMessageRequest would have filed named OperationType = OperationTypes.CreateCustomer and rest of fields would provide enough information for the service that it could create Customer object or record in database or whatever. And IMessageResult could have field with some code for indication that customer was created or not.
What I'm trying to achieve by such design is an ability to easy delegate IMessageRequest to other internal services that client side wouldn't even know about. Another benefit I see is that if we will have to add some operation on customers we only provide additional DataContract for this operation and don't have to change anything on service interface side (I want to avoid this at all costs, I mean not new operations but changing service interface :)
So, what do you think? Is it good way of handling complicated business processes? What are pitfals, what could be better.
If I duplicated some other thread and there are some answers to my question please provide me with links because I didn't find them.
Short answer: yes, this could be a very good idea (and one I have implemented in one form or another a couple of times).
A good starting point for this type of approach are the posts by Davy Brion on what he calls the request/response layer. He consolidated his initial ideas & thoughts into a very usable OSS project called Agatha, which I am proposing at a customer site as I write this.
This is exactly what we're doing here where I work. It works great and is easy for all the developers to understand, and really easy to wire up new methods/class/etc.
I'm developing and application that runs as a Windows service. There are other components which include a few WCF services, a client GUI and so on - but it is the Windows service that access the database.
So, the application is a long-running server, and I'd like to improve its performance and scalability, I was looking to improve data access among other things. I posted in another thread about second-level caching.
This post is about session management for the long-running thread that accesses the database.
Should I be using a thread-static context?
If so, is there any example of how that would be implemented.
Every one around the net who is using NHibernate seem to be heavily focussed on web-application style architectures. There seems to be a great lack of documentation / discussion for non-web app designs.
At the moment, my long running thread does this:
Call 3 or 4 DAO methods
Verify the state of the detached objects returned.
Update the state if needed.
Call a couple of DAO methods to persist the updated instances. (pass in the id of the object and the instance itself - the DAO will retrieve the object from the DB again, and set the updated values and session.SaveOrUpdate() before committing the transaction.
Sleep for 'n' seconds
Repeat all over again!
So, the following is a common pattern we use for each of the DAO methods:
Open session using sessionFactory.OpenSession()
Begin transaction
Do db work. retrieve / update etc
Commit trans
(Rollback in case of exceptions)
Finally always dispose transaction and session.Close()
This happens for every method call to a DAO class.
I suspect this is some sort of an anti-pattern the way we are doing it.
However, I'm not able to find enough direction anywhere as to how we could improve it.
Pls note, while this thread is running in the background, doing its stuff, there are requests coming in from the WCF clients each of which could make 2-3 DAO calls themselves - sometimes querying/updating the same objects the long running thread deals with.
Any ideas / suggestions / pointers to improve our design will be greatly appreciated.
If we can get some good discussion going, we could make this a community wiki, and possbily link to here from http://nhibernate.info
Krishna
There seems to be a great lack of documentation / discussion for non-web app designs.
This has also been my experience. However, the model you are following seems correct to me. You should always open a session, commit changes, then close it again.
This question is a little old now, but another technique would be to use Contextual Sessions rather than creating a new session in each DAO.
In our case, we're thinking of creating the session once per thread (for our multi-threaded win32 service), and make it available to the DAOs using either a property that returns SessionFactory.GetCurrentSession() (using the ThreadContext current session provider, so it's session-per-thread) or via DI (dependency injection - once again using ThreadContext.)
More info on GetCurrentSession and Contextual Sessions here.
You can also flush the session without actually closing it and it achieves the same thing. I do.
We've recently started using an IoC container to manage session lifecycle, as a replacement for the contextual sessions mentioned above. (More details here).
I agree, there aren't many examples for stateful apps.
I'm thinking of doing the following:
Like you I have a windows service hosting a number of WCF services. So the WCF services are the entry points.
Ultimately all my WCF services inherit from AbstractService - which handles a lot of logging and basic DB inserts/updates.
In one of the best NHibernate posts I've seen, a HttpModule does the following:
see http://www.codeproject.com/KB/architecture/NHibernateBestPractices.aspx
private void BeginTransaction(object sender, EventArgs e) {
NHibernateSessionManager.Instance.BeginTransaction();
}
private void CommitAndCloseSession(object sender, EventArgs e) {
try {
NHibernateSessionManager.Instance.CommitTransaction();
}
finally {
NHibernateSessionManager.Instance.CloseSession();
}
}
So perhaps I should do something similar in AbstractService. So effectively I'll end up with a session per service invocation. If you examine the NHib best practices article link above, you'll see that the NHibernateSessionManager should deal with everything else, as long as I open and close the session (AbstractService constructor and destructor).
Just a thought. But I'm experiencing errors because my session seems to be hanging around for too long, and I'm getting the infamous error - NHibernate.AssertionFailure: null id in entry (don't flush the Session after an exception occurs).