Reputation: 5519
I'm working with single-tier, single-user applications, with FluentNHibernate. With multiple threads, triggered by time triggers and incoming socket message triggers.
What requirements will determine if I can create/dispose the ISession inside each method of the repositories, or if I need to maintain the ISession lifecycle over multiple calls, maybe from program start to end?
For example, does lazy-load require session to be maintained? And if I don't use lazyload, for what other reason should I maintain the ISession?
Currently my repository methods look like below, but I wonder if I'm doing it wrong..
public class ProductRepository
{
public void Delete(Product product)
{
using (ISession session = FNH_Manager.OpenSession())
{
using (ITransaction transaction = session.BeginTransaction())
{
session.Delete(product);
transaction.Commit();
}
}
}
class FNH_Manager
{
private static Configuration cfg;
private static ISessionFactory sessionFactory;
public static void ConfigureSessionFactory()
{
sessionFactory = CreateSessionFactory();
}
public static ISession OpenSession()
{
return sessionFactory.OpenSession();
}
EDIT1: Attempt to handle "session per call":
public class EmployeeRepository
{
public static void Delete(Employee employee)
{
using (ISession session = FNH_Manager.OpenSession())
{
using (ITransaction transaction = session.BeginTransaction())
{
if (Employee.Id != 0)
{
var emp = session.Get(typeof(Employee), employee.Id);
if (emp != null)
{
session.Delete(emp);
transaction.Commit();
}
}
}
}
}
Upvotes: 3
Views: 2876
Reputation: 2962
I think you should use UnitOfWork pattern per thread.
On thread start create ISession
and initialize UnitOfWork
with it. Repositories use UnitOfWork
with that signle ISession
. At the end of thread execution commit the changes or rollback if there was conflict with other threads.
Upvotes: 3
Reputation: 13079
The Product is not associated with any session when beeing deleted. It is a so called detached object. To use it within the session for example deleting it you need to first associate it with the currently opened session. There are several ways to achive this:
ISession.Get()
or ISession.Load()
.session
with ISession.Lock()
Otherwise you'll probably get StaleStateException
s and the like.
Remeber to read up on the NHibernate documentation
Upvotes: 1
Reputation: 41442
The session must be open when you reference a lazy-loaded field, so if you're relying on lazy-loading outside of your repository you'll need to manage the session lifespan somewhere higher up.
If you don't use lazy-loading, there's also the matter of whether you need to support multiple actions in one transaction. For example, if you delete a product AND some other data in one go, you'd want that to happen in one transaction in the same session (otherwise you might delete the product, have some code throw some exception, and never delete the other data, which may end up with orphan records or a corrupt state in your database).
Upvotes: 5