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



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

该操作对登记的当前状态无效。

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

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

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

这是我返回给定 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();

每次打开新会话是否是一种好方法,还是应该在SessionFactory中使用单例模式

先将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
NHibernate Session.Evict 是做什么的?
是否可以从 NHibernate 会话中分离对象?

编辑(用于您的更新)

每次打开新会话是否是一种好方法,还是应该在 SessionFactory 中使用单例模式?

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

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

您可以选择在请求级别移动您的 UoW(即ISession每个请求),您可以利用ORM功能的好处;但同样还有其他与之相关的问题。请参阅以下内容:https://stackoverflow.com/a/48092471/5779732
是否应将实体(持久)对象转换为 DTO 对象?

最新更新