views:

547

answers:

3

Considering the following code blocks, why does call to HQL work but call to delete() not work? As a background, I'm using NHibernate over IBM.Data.DB2.Iseries driver. Come to find out, journaling on the AS400 is turned off so I can't use transactions. I'm not the AS400 admin or know anything about it so I don't know if having journaling turned off (not opening transactions) is causing this problem or not. Do I absolutely need the ability to open transactions if I'm calling Delete() or other NHibernate functions?

//This Does not work - no error and no deletes
public static void Delete(Object Entity)
    {
        using (ISession session = _sessionFactory.OpenSession())
        {
            //using(ITransaction tx = session.BeginTransaction())
            //{
                session.Delete(Entity);
                //tx.Commit();                    
                session.Close();                    
            //}
        }
    }

//This does work
public static void Delete(Object Entity)
    {
        using (ISession session = _sessionFactory.OpenSession())
        {
            //commented out transaction control because throws error because
            //journaling is not turned on the AS400
            //using(ITransaction tx = session.BeginTransaction())
            //{
                session.CreateQuery("delete MyDAO p where p.MyDAOID = :MyDAOID").SetString("MyDAOID", ((MyDAO)Entity).MyDAOID.ToString()).ExecuteUpdate();                
            //}
        }
    }
+2  A: 

Try calling session.Flush() after you delete, but before you close the session. And you don't need to explicitly close the session:

using (var session = ...)
{
    entity.Delete();
    session.Flush();
}

HTH, Kent

Kent Boogaart
That didn't work but thanks for the advice.
Brian
A: 

After delving further into this, I found that this works but why?:

public static void Delete(Object Entity)
{
    using (ISession session = _sessionFactory.OpenSession())
    {       
         MyDAO p = session.Get<MyDAO>(Entity.ID);
         session.Delete(p);
         session.Flush();                                    
    }            
}

Here is my scenario: I have previously queried for a list of objects which I populated into a Grid. For that query process, I opened/closed a session. Upon calling my delete function, I take that object and pass it into this function for a separate open/close session process. To stir things up a bit, I added the call to this new delete asking it to get the object first (the one I want deleted), then call delete. Now it sends the delete query to the database and the object is in fact deleted. Why is this?

Is this because my original query of objects was opened within a different session and then deleted in another? Does this have anything to do with the unit of work. Should I open my session for my grid, leave it open until my form closes so all deletes work inside that session? I was under the impression that sessions should be opened/closed quickly. I'm confused.

Brian
1. You shouldn't open a new session for each data access method. You should open a new one for every time a user clicks a save or delete button in the UI. Use one session per unit of work. When you don't you lose the caching of the session and you will have to attach the objects retrieved by previous sessions to the session again. 2. You can change the session factory to "auto-flush"
Paco
Sorry but I'm confused by point 1 of your comment. You state that I shouldn't open a new session for each data access method but you then state that I should for each save/delete which in my terminology are data access methods. Please clarify. So, what is considered a unit of work when working with a form that has a grid? Is one uow querying the data and another uow the deletion of the data or is a uow the querying of the data and also the deletion/edit (one piece of data or all)? I attempted opening a session, querying my data/populating my grid, delete then flush, and that worked.
Brian
I can't give you an answer to that: it can be both depending on what the data is and what the user is doing with it. Martin Fowler writes about it in Patterns of Entrerprice Applications
Paco
A: 

Hay I am also trying to use NHibernate over DB2.ISeries but it is Throwing Exception

Unable to cast object of type 'IBM.Data.DB2.iSeries.iDB2Connection' to type 'System.Data.Common.DbConnection'.

Koti
Koti, not seeing your code I can only assume that you are setting DbConnection = iDB2Connection which wouldn't work. Try setting IDbConnection = iDB2Connection.
Brian