Reputation: 436
I need to update customer details. For this, I have to retrieve the entity from another session from repository and in the service, I am updating that entity. When I do this, I get an error message saying:
The operation is not valid for the current state of the enlistment.
But if I updated the entity without retrieving it from database, everything works fine.
This is how I am trying to update in Service.
Customer customer = customerService.getById(customer_payment.customer_id);
customer.deductBalance(customer_payment.discount_received);
customerService.updateCustomerDetails(customer);
This is my repository that updates the entity:
using (ISession session = SessionFactory.OpenSession)
{
using(ITransaction t = session.BeginTransaction())
{
session.SaveOrUpdate(customer);
t.Commit();
}
}
This is my function that returns the entity of the given ID:
Customer customer;
using (ISession session = SessionFactory.OpenSession)
{
customer = session.Get<Customer>(customer_id);
}
return customer;
How can I solve this problem? Thanks in advance.
Edit 1: This is what my OpenSession does:
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();
Is it a good approach to open a new session everytime or should I use Singleton pattern in SessionFactory?
Upvotes: 2
Views: 2440
Reputation: 16389
Detach the customer
from first ISession
before updating it with other. You have to expose Evict
method on repository OR have to expose ISession
outside your repository.
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);
Refer following:
https://ayende.com/blog/4282/nhibernate-cross-session-operations
What does NHibernate Session.Evict do?
Can I detach an object from an NHibernate session?
Edit (for your Update)
Is it a good approach to open a new session everytime or should I use Singleton pattern in SessionFactory?
This is opinion based question actually; but it is recommended that your ISession
should be short lived.
That said, you can create new session for each database action. But by doing this, you are missing many ORM features like Session Level Cache, Lazy Loading, Change Tracking (UoW) etc.
You can choose to move your UoW on Request level (i.e. ISession
per Request) where you can avail the benefit of ORM features; but again there are other issues associated with it. Refer following: https://stackoverflow.com/a/48092471/5779732
Should I transform Entity (Persistent) objects to DTO objects?
Upvotes: 2