Session.Delete(entity) does not work

462 views
Skip to first unread message

Veasna MUCH

unread,
Apr 21, 2014, 6:52:04 AM4/21/14
to nhu...@googlegroups.com
   I am very new to NHibernate. I try to use some NH methods. I am able to get all records in grid, save new records but no able to delete the records from db. Not even getting any kind of exception..
using the method as  NHibernateSession.Delete(entity); //entity is retrieved using GetByAirportCode("A1") //A1 is an code of the record that I want to delete. I get object with Code = "A1" but it does not delete that record from DB. When I added the code objAirportDao.CommitChanges(); the record is deleted from DB. I do no understand why do I need to apply commitchange here? It should be automatically right? if that's the need why does the Saving record does not need to applied CommitChange? 



Here is where I call delete object in default.aspx.cs



        protected void Button1_Click(object sender, EventArgs e) {
               IRepositoryFactory daoFactory = new NHibernateDaoFactory(); 
            IAirportRepository objAirportDao = daoFactory.GetAirportDao();
            Airport objAirport = objAirportDao.GetByAirportCode ("A1");
            if (objAirport != null){
                objAirportDao.Delete(objAirport);
                //objAirportDao.CommitChanges();    
 
          
            }            

        }




Class AirportRepository 



 public class AirportRepository : AbstractNHibernateRepository<Airport, int>, IAirportRepository
    {
        public AirportRepository() { }
        public Airport GetByAirportCode(string airportCode) {
            return GetByCriteria(new ICriterion[] { Expression.Eq("AirportCode", airportCode )}).ToList<Airport>().FirstOrDefault();    
        }
    }


Class NHibernateSessionFactory

   public class NHibernateSessionFactory{       
        public static NHibernateSessionFactory Instance
        {
            get {
                return Nested.NHibernateSessionFactory;
            }
        }
       
        private NHibernateSessionFactory(){
            InitSessionFactory();
        }
        
        private class Nested {
            static Nested() { }
            internal static readonly NHibernateSessionFactory NHibernateSessionFactory = new NHibernateSessionFactory();
        }
       
        private void InitSessionFactory(){
            sessionFactory = new Configuration().Configure().BuildSessionFactory();
        }
       
        public void RegisterInterceptor(IInterceptor interceptor) {
            ISession session = ContextSession;
            if (session != null && session.IsOpen)
            {
                throw new CacheException("You cannot register an interceptor once a session has already been opened");
            }
            GetSession(interceptor);
        }
        public ISession GetSession(){
            return GetSession(null);
        }
        
        private ISession GetSession(IInterceptor interceptor)  {
            ISession session = ContextSession;
            if (session == null){
                if (interceptor != null){
                    session = sessionFactory.OpenSession(interceptor);
                }else{
                    session = sessionFactory.OpenSession();
                }
                ContextSession = session;
            }           
            return session;
        }
       
        public void CloseSession(){
            ISession session = ContextSession;
            if (session != null && session.IsOpen){
                session.Flush();
                session.Close();
            }
            ContextSession = null;
        }
 
        public void BeginTransaction() {
            ITransaction transaction = ContextTransaction;
            if (transaction == null){
                transaction = GetSession().BeginTransaction();
                ContextTransaction = transaction;
            }
        }
 
        public void CommitTransaction(){
            ITransaction transaction = ContextTransaction;
            try
            {
                if (HasOpenTransaction()) {
                    transaction.Commit();
                    ContextTransaction = null;
                }
            } catch (HibernateException){
                RollbackTransaction();
                throw;
            }
        }
 
        public bool HasOpenTransaction(){
            ITransaction transaction = ContextTransaction;
            return transaction != null && !transaction.WasCommitted && !transaction.WasRolledBack;
        }
 
        public void RollbackTransaction(){
            ITransaction transaction = ContextTransaction;
            try
            {
                if (HasOpenTransaction()){
                    transaction.Rollback();
                }
                ContextTransaction = null;
            }
            finally
            {
                CloseSession();
            }
        }
       
        private ITransaction ContextTransaction{
            get
            {
                if (IsInWebContext()){
                    return (ITransaction)HttpContext.Current.Items[TRANSACTION_KEY];
                }else{
                    return (ITransaction)CallContext.GetData(TRANSACTION_KEY);
                }
            }
            set
            {
                if (IsInWebContext()){
                    HttpContext.Current.Items[TRANSACTION_KEY] = value;
                }else{
                    CallContext.SetData(TRANSACTION_KEY, value);
                }
            }
        }
       
        private ISession ContextSession{
            get
            {
                if (IsInWebContext())
                {
                    return (ISession)HttpContext.Current.Items[SESSION_KEY];
                }
                else
                {
                    return (ISession)CallContext.GetData(SESSION_KEY);
                }
            }
            set
            {
                if (IsInWebContext())
                {
                    HttpContext.Current.Items[SESSION_KEY] = value;
                }
                else
                {
                    CallContext.SetData(SESSION_KEY, value);
                }
            }
        }
 
        private bool IsInWebContext() {
            return HttpContext.Current != null;
        }
        private const string TRANSACTION_KEY = "CONTEXT_TRANSACTION";
        private const string SESSION_KEY = "CONTEXT_SESSION";
        private ISessionFactory sessionFactory;
    }




Here is my abstract class AbstractNHibernateRepository:


public abstract class AbstractNHibernateRepository<T, IdT> : IRepository<T, IdT> {
      
   public T GetById(IdT id, bool shouldLock){
            T entity;
            if (shouldLock) {
                entity = (T)NHibernateSession.Load(persitentType, id, LockMode.Upgrade);
            } else {
                entity = (T)NHibernateSession.Load(persitentType, id);
            }
            return entity;
        }
        public List<T> GetAll() {
            return GetByCriteria();
        }
        public List<T> GetByCriteria(params ICriterion[] criterion) {
            ICriteria criteria = NHibernateSession.CreateCriteria(persitentType);
            foreach (ICriterion criterium in criterion)
            {
                criteria.Add(criterium);
            }
            return criteria.List<T>() as List<T>;
        }
        public List<T> GetByExample(T exampleInstance, params string[] propertiesToExclude)  {
            ICriteria criteria = NHibernateSession.CreateCriteria(persitentType);
            Example example = Example.Create(exampleInstance);
            foreach (string propertyToExclude in propertiesToExclude)  {
                example.ExcludeProperty(propertyToExclude);
            }
            criteria.Add(example);
            return criteria.List<T>() as List<T>;
        }
       
 
        public T GetUniqueByExample(T exampleInstance, params string[] propertiesToExclude) {
            List<T> foundList = GetByExample(exampleInstance, propertiesToExclude);
            if (foundList.Count > 1) {
                throw new NonUniqueResultException(foundList.Count);
            }
            if (foundList.Count > 0){
                return foundList[0];
            } else {
                return default(T);
            }
        }
       
 
        public T Save(T entity){
            NHibernateSession.Save(entity);
            return entity;
        }
        
        public T SaveOrUpdate(T entity) {
            NHibernateSession.SaveOrUpdate(entity);
            return entity;
        }
 
        public void Delete(T entity){
            NHibernateSession.Delete(entity);
        }
       
        public void CommitChanges() {
            if (NHibernateSessionFactory.Instance.HasOpenTransaction())
            {
                NHibernateSessionFactory.Instance.CommitTransaction();
            } else{              
                NHibernateSessionFactory.Instance.GetSession().Flush();
            }
        }
       
        private ISession NHibernateSession{
            get {
                return NHibernateSessionFactory.Instance.GetSession();
            }
        }
        private Type persitentType = typeof(T);
    }




Ricardo Peres

unread,
Apr 21, 2014, 7:16:03 AM4/21/14
to nhu...@googlegroups.com
This has to do with the FlushMode of the ISession. By default, you have to explicitly Flush the ISession manually, or, if you start and commit a transaction, it is done for you.
This is by design, pretty much like Entity Framework, where you have to call SaveChanges.

RP

Veasna MUCH

unread,
Apr 21, 2014, 10:12:07 PM4/21/14
to nhu...@googlegroups.com
Dear RP,

By the way, in Save(T entity) or SaveOrUpdate(T entity), why does the record is save in the database without needed to applied Flush? 

Is that needed only for deleting record? 
        public void Delete(T entity) {
            NHibernateSession.Delete(entity);
            NHibernateSession.Flush();  
        }


Best regards,

Veasna

Gunnar Liljas

unread,
Apr 22, 2014, 2:06:42 AM4/22/14
to nhu...@googlegroups.com
It's inserted if that's required to get a new primary key value, i.e if you have you identity key generators.


--
You received this message because you are subscribed to the Google Groups "nhusers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to nhusers+u...@googlegroups.com.
To post to this group, send email to nhu...@googlegroups.com.
Visit this group at http://groups.google.com/group/nhusers.
For more options, visit https://groups.google.com/d/optout.

Ricardo Peres

unread,
Apr 22, 2014, 3:10:24 AM4/22/14
to nhu...@googlegroups.com
As Gunnar said, you are probably using a DB-generated primary key generator, this breaks the Unit of Work pattern in the sense that it does not send everything at the same time to the database.

RP

Oskar Berggren

unread,
Apr 22, 2014, 5:40:20 AM4/22/14
to nhu...@googlegroups.com
Just wanted to add that:

a) You should almost always perform your changes inside a transaction.
b) You do probably not want to sprinkle calls to Flush() in the Delete() method or other "low-level" methods. When NH performs a flush it will dirty-check all active objects known by the current NH session. Therefore flushing too often is bad for performance.

/Oskar



2014-04-22 4:12 GMT+02:00 Veasna MUCH <veasn...@gmail.com>:

Veasna MUCH

unread,
Apr 22, 2014, 3:23:58 AM4/22/14
to nhu...@googlegroups.com
Dear RP and Gunnar,

Here is my table schemas

Inline image 1



and my mapping file

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
  <class name="Tec.Core.Model.Airport, Tec.Core" table="tblAirport" lazy="false">
    <id name="ID" column="AirportID" unsaved-value="0">
      <generator class="identity" />
    </id>

    <property name="AirportCode" column="AirportCode" />
    <property name="AirportFullName" column="AirportFullName" />

    
  </class>
</hibernate-mapping>


  You are right RP,  that I used DB-generated primary key generator. As I am new to NHibernate, I would preferred to have something more proper. Please guide me how could I have a better implementation?  

What does the meaning of breaks the Unit of Work pattern in the sense that it does not send everything at the same time to the database.?

Best regards,

Veasna


--
You received this message because you are subscribed to a topic in the Google Groups "nhusers" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/nhusers/svafC-vVlAI/unsubscribe.
To unsubscribe from this group and all its topics, send an email to nhusers+u...@googlegroups.com.

Veasna MUCH

unread,
Apr 22, 2014, 7:47:13 AM4/22/14
to nhu...@googlegroups.com
Dear Oskar,

   I was configured at web.config with the following statement
<httpModules>
<add name="NHibernateSessionModule" type="Tec.Web.NHibernateSessionModule"/>
</httpModules>

by thinking that the transaction is begin and close on each request

 public class NHibernateSessionModule : IHttpModule
    {
        public void Init(HttpApplication context) {
            context.BeginRequest += new EventHandler(BeginTransaction);
            context.EndRequest += new EventHandler(CommitAndCloseSession);
        }

          private void BeginTransaction(object sender, EventArgs e) {
            NHibernateSessionFactory.Instance.BeginTransaction();
        }

           private void CommitAndCloseSession(object sender, EventArgs e) {
            try {
                NHibernateSessionFactory.Instance.CommitTransaction();
            } finally {
                NHibernateSessionFactory.Instance.CloseSession();
            }
        }
 }

That's not a proper way right?

Best regards,

Veasna


--
You received this message because you are subscribed to a topic in the Google Groups "nhusers" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/nhusers/svafC-vVlAI/unsubscribe.
To unsubscribe from this group and all its topics, send an email to nhusers+u...@googlegroups.com.

Oskar Berggren

unread,
Apr 22, 2014, 9:03:42 AM4/22/14
to nhu...@googlegroups.com
It's common to use something along those lines yes. You might consider doing rollback instead of commit if there is an error, otherwise you might get "half" the job committed.

There are various strategies for handling the session. I often use a NH session for one http request only as this makes the web server carry less state. But some patterns use a single NH session for several requests.

NH has some built-in methods to help with contextual sessions that might help you:
http://www.nhforge.org/doc/nh/en/#architecture-current-session

/Oskar

Reply all
Reply to author
Forward
0 new messages