I am writing a wcf service and i wanna use NHibernate for the data access objects. My doubt is about how would be the best approach to handle the nh's sessions.
I've been reading about the topic and seems like per call is the best way, also i found the uNhAddIns implementation, but does anyone know if this is a better choice?
any advice will be appreciated.
Have one NHibernateSessionFactory class such that we always get a single instance of the NHibernate session factory and start using them in wcf service on need basis. You can have a
instance of this in the class implementing the operation contracts
private readonly NHibernateSessionFactory m_sessionfactory = new NHibernateSessionFactory();
you can start using it on need basis with in the class:
using (ISession session = m_sessionfactory.Instance().OpenSession())
{
//----------Do something here
}
I am not sure whether you are looking for these type of details or not. If not please ingnore my response.
Related
I'm creating a web forms project in c#.
One of the key requirements is to post out to an API, however there's not one but several API's available.
At present the HttpClient object is uniquely defined for each API in a different namespace, like below:
MyCo.Myapp.PostApi.Client1.ClientObject
MyCo.Myapp.PostApi.Client2.ClientObject
Aside from the HttpClient, the endpoint url and mediatypes are stored as well as a few other configuration objects.
The idea being that the namespace Client1 or Client2 is stored in a database, and can be used to retrieve the location of the correct API, to create the object.
None of the above is set in stone - it's in concept form - so I wondered if there are any other alternatives to this solution which I can consider.
Any advice appreciated.
This seems like a potential candidate for an Abstract Factory approach. What you're describing sounds familiar to how one would connect to various database types using System.Data.Common
var settings = GetInfoFromDatabase();
var factory = ClientObjectFactory.Create(settings);
var clientObject = factory.CreateClientObject();
clientObject.Post(""); // This could be any of the client objects.
However since you don't have control over client APIs you could have the underlying factory perform the post:
factory.Post(clientObject, data);
All of our services take a ServiceCallContext object as a parameter. The service then creates a broker and tells the broker what connection string to use based on the ServiceCallContext.
In other words, some of our customers have their own databases so the service calls have to point the brokers to their databases.
I would like to take the code that looks at the ServiceCallContext and chooses the correct connection and put it in a base service class. My team lead doesn't like that idea because with services he feels that this would be 'hiding' behavior and that this would be a bad thing. He suggested that there may be better ways to accomplish the same thing through some sort of WCF extensions.
I honestly don't care how we implement the code so long as I can reuse it because I think it's absolutely silly for me to be rewriting it in every service I create. I began looking into some WCF videos on PluralSight and it looks like there's a lot of great stuff it can do but unfortunately I'm not quite sure where to start. Can anyone give me a little direction as to whether WCF can accomplish what I'm trying to do and if so what particular features of WCF am I looking for?
The functionality you need is a custom interceptor.
This allows you to tell the WCF stack to look at incoming messages and the do some action based on them. If you wrap the interceptor up into it's own assembly then you can reference it from multiple services.
How should I manage my session? I've seen some examples where the session is created in the constructor of the domainservice and destroyed in the dispose method, but this seems like a bad idea.
Would appreciate help here because I can't find any information.
I don't know RIA Services very well but it's based on WCF so maybe you can use the pattern of one session for each Operation, like in web you can use the pattern Session per Request ?
http://www.google.ca/search?hl=en&safe=off&q=WCF+Nhibernate+operation+context&aq=f&aqi=&aql=&oq=&gs_rfai=
and the first response give some code :
http://realfiction.net/go/133
The next version of NHibernate, the integration of WCF should be built-in, here'sthe source code from the trunk :
https://nhibernate.svn.sourceforge.net/svnroot/nhibernate/trunk/nhibernate/src/NHibernate/Context/WcfOperationSessionContext.cs
In my DefaultRegistry I have this configuration:
ForRequestedType<INHUnitOfWork>().CacheBy(InstanceScope.HttpContext)
.TheDefault.Is.OfConcreteType<NHibernateUnitOfWork>();
At some point in the web application flow I want to change the InstanceScope to HttpSession to obtain a long conversation, so I do this:
PluginTypeConfiguration config = ObjectFactory.Model.PluginTypes.FirstOrDefault(p => p.PluginType.FullName.Contains("INHUnitOfWork"));
config.Lifecycle.EjectAll();
config.Lifecycle = StructureMap.Pipeline.Lifecycles.GetLifecycle(InstanceScope.HttpSession);
This seems to replace the initial InstanceScope, unfortunately it lasts only for the current request. When the next request arrives, the initial configuration is active again and the session information is lost.
Later I also want to be able to revert the change with something like this:
PluginTypeConfiguration config = ObjectFactory.Model.PluginTypes.FirstOrDefault(p => p.PluginType.FullName.Contains("INHUnitOfWork"));
config.Lifecycle.EjectAll();
config.Lifecycle = StructureMap.Pipeline.Lifecycles.GetLifecycle(InstanceScope.HttpContext);
but if I will make it work in one direction it will probably work in both.
Is it possible to replace the initial InstanceScope permanently at runtime? How should this be implemented?
Also, do you think this a good way to obtain a long conversation or there is a better / simpler way to do it with StructureMap & NHibernate?
Take a look at Ayende's detailed explanation on how to enable long running conversations and UnitOfWork:
http://ayende.com/Wiki/Default.aspx?Page=HttpModules&AspxAutoDetectCookieSupport=1
I would recommend creating a UnitOfWorkApplication module and make it responsible for creating a UnitOfWork instance and adding it to the container before your code executes (before the request is processed, like in the example). This way you have more flexibility and control over how unit of work is created.
It sounds slightly strange to me what you are trying to do. Routes I'd try would be
Configure a named instance in StructureMap that also implements said interface but is scoped differently. You can inject different dependencies for different interface consumer, maybe that helps?
Write your own CacheInterceptor that effectively implements your specific lifecycle.
The latter is done e.g. here for WCF lifecycle: http://blogs.rpionline.com/post/2009/02/How-to-use-NHibernate-and-StructureMap-in-a-WCF-application.aspx
On my quest to learn NHibernate I have reached the next hurdle; how should I go about integrating it with StructureMap?
Although code examples are very welcome, I'm more interested in the general procedure.
What I was planning on doing was...
Use Fluent NHibernate to create my class mappings for use in NHibs Configuration
Implement ISession and ISessionFactory
Bootstrap an instance of my ISessionFactory into StructureMap as a singleton
Register ISession with StructureMap, with per-HttpRequest caching
However, don't I need to call various tidy-up methods on my session instance at the end of the HttpRequest (because thats the end of its life)?
If i do the tidy-up in Dispose(), will structuremap take care of this for me?
If not, what am I supposed to do?
Thanks
Andrew
I use StructureMap with fluent-nhibernate (and NH Validator) in 3 of my current projects. 2 of those are ASP MVC apps and the third is a WCF web service.
Your general strategy sounds about right (except you won't be making your own Session or SessionFactory, as was already pointed out in comments). For details, snag my configuration code from here:
http://brendanjerwin.github.com/development/dotnet/2009/03/11/using-nhibernate-validator-with-fluent-nhibernate.html
The post is really about integrating NH Validator and Fluent-NHibernate but you can see exactly how I register the session factory and ISession with StructureMap in the "Bonus" section of the post.
RE: Tidy up: You should try and always work within a transaction and either commit or roll-back the transaction at the end of your unit of work. NH only utilizes SQL Connections when it needs them and will take care of the cleanup of that limited resource for you. Normal garbage collection will take care of your sessions themselves.
The Session Factory is a very expensive object that you will want to only initialize once and keep around for the life of your app.
I've not used structure map but maybee I can still help guide you in the right direction. Fluent nHibernate is awsome good choice over the hbm files.
As for the http request, you do not need to ensure that you close the session when the http request ends. If you don't you'll end up leaking nHibernate session. I'm not sure if structure map will handle this for you, what I've done is I have an http module which closes the session.
One thing to note though that bite me, is that you will make to sure you wrap all your data access in a transaction and ensure nHibernate actually commits its changes. If you do this as part of your session close, you could miss the chance to handle errors. I'm curious to hear what you ended up having to do to get this workign.