2

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?

Dot Net developer
  • 436
  • 1
  • 5
  • 19
  • https://stackoverflow.com/questions/3390561/nhibernate-update-single-field-without-loading-entity?noredirect=1&lq=1 – Ankush Jain Jan 06 '18 at 12:02
  • What's inside the OpenSession property? You need to ensure that you attach to the existing session instead of creating/opening a new one. – Denis Ivin Jan 07 '18 at 17:49
  • @DenisIvin sir I have edited my question. Can you have a look at it once? I have added one more question at last . Sorry for that as my intention initially was another question. Can you please help me out on the second one also. – Dot Net developer Jan 08 '18 at 07:47

1 Answers1

1

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?

Amit Joshi
  • 15,448
  • 21
  • 77
  • 141