NHibernate ISession生命周期;何时可以在每个存储库方法中创建/部署?

时间:2011-02-01 21:45:23

标签: c# .net database nhibernate repository

我正在使用 FluentNHibernate 单层单用户应用程序。使用多个线程,由时间触发器和传入套接字消息触发器触发。

哪些要求将决定我是否可以在存储库的每个方法中创建/处置 ISession ,或者我是否需要在多个调用中维护ISession生命周期,可能是从程序开始到结束?

例如,延迟加载是否需要维护会话?如果我不使用lazyload,还有其他原因我应该维护ISession吗?

目前我的存储库方法如下所示,但我想知道我做错了..

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: 尝试处理“每次通话会话”:

   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();
                      }
                    }
                }
            }
        } 

3 个答案:

答案 0 :(得分:5)

当您引用延迟加载的字段时,会话必须打开,因此如果您依赖于存储库之外的延迟加载,则需要在更高的位置管理会话生命周期。

如果您不使用延迟加载,还需要在一个事务中支持多个操作。例如,如果您一次删除产品和其他一些数据,您希望在同一会话中的一个事务中发生这种情况(否则您可能会删除该产品,让某些代码抛出一些异常,并且永远不会删除其他数据,可能以数据库中的孤儿记录或损坏状态结束。)

答案 1 :(得分:3)

我认为你应该为每个线程使用UnitOfWork模式。 在线程开始时创建ISession并使用它初始化UnitOfWork。存储库使用UnitOfWork使用该符号ISession。在线程执行结束时,如果与其他线程发生冲突,则提交更改或回滚。

答案 2 :(得分:1)

删除时,产品与任何会话无关。它是一个所谓的分离对象。要在会话中使用它,例如删除它,您需要先将其与当前打开的会话相关联。有几种方法可以实现这一目标:

  1. 保持会话开放。如果在加载产品时打开相同的会话,就像删除产品一样,它将正常工作。
  2. 重新加载对象,但使用ISession.Get()ISession.Load()
  3. 使用session
  4. 将对象重新附加到新打开的会话ISession.Lock()

    否则你可能会得到StaleStateException之类的东西。

    记得阅读NHibernate documentation