从一个会话中检索对象并在另一个会话中更新 nHibernate

Retrieving an object from one session and updating in another session nHibernate

我需要更新 客户 详细信息。为此,我必须从存储库的另一个会话中检索实体,并在 服务 中更新该实体。当我这样做时,我收到一条错误消息:

The operation is not valid for the current state of the enlistment.

但是如果我更新实体而不从数据库中检索它,一切正常。

这就是我在 Service 中尝试更新的方式。

 Customer customer = customerService.getById(customer_payment.customer_id);
 customer.deductBalance(customer_payment.discount_received);
 customerService.updateCustomerDetails(customer);

这是我更新实体的存储库

using (ISession session = SessionFactory.OpenSession)
  {
    using(ITransaction t = session.BeginTransaction())
        {
          session.SaveOrUpdate(customer);
           t.Commit();
        }
   }

这是我的函数,returns 给定 ID 的实体:

客户客户;

using (ISession session = SessionFactory.OpenSession)
  {
   customer = session.Get<Customer>(customer_id);
  }
 return customer;

我该如何解决这个问题?提前致谢。

编辑 1: 这就是我的 OpenSession 所做的:

Configuration configuration = new Configuration().Configure("hibernate.cfg.xml");
Assembly assembly = Assembly.GetCallingAssembly();
configuration.AddAssembly(assembly);
iSessionFactory = configuration.BuildSessionFactory();
CurrentSessionContext.Bind(iSessionFactory.OpenSession());
return iSessionFactory.OpenSession();

每次打开一个新的 session 是个好方法还是我应该在 SessionFactory[ 中使用 Singleton pattern =42=]?

先将 customer 与第一个 ISession 分离,然后再更新为其他。您必须在存储库上公开 Evict 方法,或者必须在存储库外部公开 ISession

Customer customer = customerService.getById(customer_payment.customer_id);

customerService.Evict(customer);
//OR
customerRepository.Evict(customer);
//OR
customerService.Session.Evict(customer);
//OR something similar...

customer.deductBalance(customer_payment.discount_received);
customerService.updateCustomerDetails(customer);

参考以下内容:
https://ayende.com/blog/4282/nhibernate-cross-session-operations
What does NHibernate Session.Evict do?
Can I detach an object from an NHibernate session?

编辑(为您更新)

Is it a good approach to open a new session everytime or should I use Singleton pattern in SessionFactory?

这实际上是基于意见的问题;但建议您 ISession 应该是短暂的。

也就是说,您可以为每个数据库操作创建新会话。但是通过这样做,您将错过许多 ORM 功能,如会话级缓存、延迟加载、更改跟踪 (UoW) 等。

您可以选择将 UoW 移动到请求级别(即每个请求 ISession),以便您可以利用 ORM 功能;但同样还有其他与之相关的问题。参考以下内容:
Should I transform Entity (Persistent) objects to DTO objects?