NHibernate-为什么Delete()调用无法删除,但通过HQL删除可以工作?

NHibernate-为什么Delete()调用无法删除,但通过HQL删除可以工作?,nhibernate,transactions,db2,ibm-midrange,Nhibernate,Transactions,Db2,Ibm Midrange,考虑到以下代码块,为什么对HQL的调用有效,但对delete()的调用无效?作为背景,我在IBM.Data.DB2.Iseries驱动程序上使用NHibernate。来看看吧,AS400上的日志记录已关闭,因此我无法使用事务。我不是AS400管理员或对此一无所知,所以我不知道关闭日志记录(而不是打开事务)是否会导致此问题。如果调用Delete()或其他NHibernate函数,是否绝对需要打开事务的功能 //This Does not work - no error and no deletes

考虑到以下代码块,为什么对HQL的调用有效,但对delete()的调用无效?作为背景,我在IBM.Data.DB2.Iseries驱动程序上使用NHibernate。来看看吧,AS400上的日志记录已关闭,因此我无法使用事务。我不是AS400管理员或对此一无所知,所以我不知道关闭日志记录(而不是打开事务)是否会导致此问题。如果调用Delete()或其他NHibernate函数,是否绝对需要打开事务的功能

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

尝试在删除后,但在关闭会话之前调用会话.Flush()。您不需要显式关闭会话:

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

深入研究后,我发现这是可行的,但为什么呢?:

public static void Delete(Object Entity)
{
    using (ISession session = _sessionFactory.OpenSession())
    {       
         MyDAO p = session.Get<MyDAO>(Entity.ID);
         session.Delete(p);
         session.Flush();                                    
    }            
}
publicstaticvoiddelete(对象实体)
{
使用(ISession session=\u sessionFactory.OpenSession())
{       
mydaop=session.Get(Entity.ID);
删除(p);
session.Flush();
}            
}
下面是我的场景:我之前查询了一个填充到网格中的对象列表。对于该查询过程,我打开/关闭了一个会话。在调用delete函数时,我获取该对象并将其传递到该函数中,以进行单独的打开/关闭会话过程。为了让事情变得更糟,我给这个新的delete添加了一个调用,要求它首先获取对象(我想要删除的对象),然后调用delete。现在它将删除查询发送到数据库,对象实际上已被删除。为什么会这样


这是因为我最初的对象查询是在另一个会话中打开的,然后在另一个会话中删除的吗?这与工作单位有关吗。我是否应该打开网格的会话,让它一直打开,直到我的表单关闭,以便所有删除操作都可以在该会话中进行?我的印象是会议应该很快开始/结束。我很困惑。

您是否遇到异常情况,消息是什么?如果您没有得到异常,会话将生成什么sql。删除?Paco,我没有收到异常,也没有生成删除查询。请看我对这篇文章的其他回复(我在看到你的评论后发布)。如果我调用Get函数来检索会话中的对象,然后告诉它在该会话中删除,它就会生成删除查询。那么,为什么我没有收到异常?我了解到了这一点,因为我在一个会话中查询了一个对象列表,然后关闭了它,并试图从另一个会话中删除该对象,它不起作用——因为我想它不在同一个工作单元内。然而,抛出和异常,这样我就知道我的对象没有删除,这难道不是很好吗?1。您不应该为每个数据访问方法打开新会话。每次用户单击UI中的“保存”或“删除”按钮时,都应该打开一个新的。每个工作单元使用一个会话。如果没有,则会丢失会话的缓存,并且必须将以前会话检索到的对象再次附加到会话。2.您可以将会话工厂更改为“自动刷新”,很抱歉,我对您评论的第1点感到困惑。您声明我不应该为每个数据访问方法打开新会话,但您随后声明我应该为每个保存/删除(在我的术语中是数据访问方法)打开新会话。请澄清。那么,在使用具有网格的表单时,什么被视为工作单元?一个uow是查询数据,另一个uow是删除数据,还是一个uow是查询数据,同时也是删除/编辑(一条数据或全部数据)?我尝试打开一个会话,查询我的数据/填充我的网格,删除然后刷新,这一切都起了作用。我无法给你答案:这可能取决于数据是什么以及用户对数据做了什么。Martin Fowler在Enterprice应用程序模式中写到了这一点。这确实对我有用,我很想知道为什么。我使用相同的会话获取所有实体。我有一种感觉,这是因为在提交事务之前希望进行删除的情况比较少见。NHibernate可能只是打算让这一切在以后发生,这通常是可以的。