2

我对 Session.Clear() 有疑问,据我了解,此语句应完全重置在 UOW、缓存等中所做的所有更改。问题是事实并非如此。下面的测试说明了我的情况。我添加到项目,它们之间存在依赖关系然后我尝试删除另一个项目所依赖的项目。这将导致一个正确的异常。然后我清除会话。最后我尝试向数据库添加一个新项目,当刷新 NHibernate 将再次尝试执行失败的删除语句。我是否误解了 Session.Clear() 的使用?还是我在这里错过了其他东西?

    [Fact]
    public void Verify_Cant_Clear_Delete()
    {
        var session = SessionFactory.OpenSession();

        var category = new ManufacturerCategory { Name = "category" };
        var man = new Manufacturer { Category = category, Name = "man" };

        session.Save(category);
        session.Save(man);
        session.Flush();

        try
        {
            // this will cause
            // NHibernate.Exceptions.GenericADOException: could not execute batch command.[SQL: SQL not available]
            // ---> System.Data.SqlClient.SqlException: The DELETE statement conflicted with the REFERENCE constraint "ManufacturerCategoryId". 
            // The conflict occurred in database "LabelMaker-Tests", table "dbo.Manufacturers", column 'Category_id'.

            session.Delete(category);
            session.Flush();

        }
        catch (Exception ex)
        {
            // This should clear the session
            session.Clear();    
        }

        try
        {
            var category2 = new ManufacturerCategory { Name = "category 2" };
            session.Save(category2);
            session.Flush();
        }
        catch(Exception ex)
        {
            // this will cause ONCE AGAIN cause
            // NHibernate.Exceptions.GenericADOException: could not execute batch command.[SQL: SQL not available]
            // ---> System.Data.SqlClient.SqlException: The DELETE statement conflicted with the REFERENCE constraint "ManufacturerCategoryId". 
            // The conflict occurred in database "LabelMaker-Tests", table "dbo.Manufacturers", column 'Category_id'.

            Assert.True(false);
        }
    } 
4

2 回答 2

2

您应该使用事务并在休眠异常上回滚事务,因为...

ISession 的某些方法不会使会话保持一致状态。

http://nhibernate.info/doc/nh/en/index.html#manipulatingdata-exceptions

或者让事务通过 dispose() 隐式回滚...

using (ISession sess = factory.OpenSession())
using (ITransaction tx = sess.BeginTransaction())
{
    // do some work
    ...
    tx.Commit();
}

我猜想 Delete() 方法是上面引用中暗示的不一致状态方法之一......

于 2013-01-03T21:04:17.287 回答
1

你的假设ISession.Clear()是不正确的。

特别是,一旦发生异常,您必须丢弃会话。Clear()不会修复状态(查看9.8 异常处理

此外,正如 dotjoe 所提到的,您应该使用事务来完成工作。

于 2013-01-06T00:49:56.363 回答