I have an MVC project that I exclusively employ a custom "Unit Of Work" pattern that uses NHibernate on the back end, which I expose to my application as IUnitOfWork
and IUnitOfWorkFactory
interfaces; These interfaces are injected as my NHibernate implementations via Ninject.
I use my UOW in a modified "session per request" style... I explicitly generate my IUnitOfWork
from my injected IUnitOfWorkFactory
when I need to perform database operations; it seems much easier to keep the CRUD where it belongs (out of my views and controllers) and effectively prevents accidental N+1 coding issues. Of course, it's a little harder to implement, but to date, I've been pretty happy with it.
Now I want to implement a WebAPI presenting IQueryable<Entity>
-style REST calls, and my UOW pattern isn't digging it. The Queryables invariably blow up, attempting to invoke a disposed NHibernate session.
I've read some stuff online about how to implement a DelegatingHandler
to manage the session for a WebAPI call... but I see several problems:
ISession
to the web application, using a built-in NHibernate mechanism ( CurrentSessionContext.Bind(ISession)
); I'd much rather reference my IUnitOfWork
interface, and trust it to maintain the session it needs to. So my question is, how can I implement a IQueryable<Entity>
RESTful API using my own IUnitOfWork
interface going against loosely-coupled NHibernate back-end?
You would face the same problem with a straightforward session-per-request implementation. For example:
// GET api/companies
public IQueryable<Company> GetCompanies()
{
return _session.Query<Company>();
}
I usually wrap all database operations, including selects, in a transaction but because query execution is deferred I can't do it in this method. It is possible to do so by creating an ActionFilter and overriding OnActionExecuted but the difficulty is gaining a reference to the ISession or your IUnitOfWork implementation in the filter. There are examples of how to accomplish this using Ninject and other dependency injection frameworks on the web.
Personally I don't see the value of abstracting the ISession, especially in Web API where it would be very rare to have a resource that did not perform a database operation. Session-per-conversation is definitely not a good pattern for this; it generally refers to keeping a session open over multiple server round trips.
My preferred architecture is to use Ninject to manage ISessionFactory and ISession lifetime (singleton and per-request, respectively) and to inject the ISession into the Api controllers. But you could also inject it into a repository or unit of work implementation.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.