NHibernate - 删除行推迟到 Commit(),但不会添加行。

NHibernate - deleting row is postponed to Commit(), but adding row not.

我的问题是NHibernate延迟了删除行的操作,而其他操作没有延迟,导致异常。 在我的数据库中,我的用户 table 具有唯一字段:登录。

我正在使用 NHibernate 5.1.3、.NET 版本 4.6.1、C#。 下面我粘贴了导致问题的代码片段:

        var user1 = new UserEntity(0, "John1", "Smith1", "login1", "password2");
        var user2 = new UserEntity(0, "John2", "Smith2", "login1", "password2");
        using (var tx = _session.BeginTransaction())
        {
            //_session.FlushMode = FlushMode.Always; //this does not help 
            _userRepository.Add(user1);
            _userRepository.Delete(user1);
            //_session.Flush(); uncommenting this helps 
            _userRepository.Add(user2);
            Console.WriteLine(tx.IsActive.ToString());
            Console.WriteLine("_session.IsOpen.ToString() = " + _session.IsOpen.ToString());
            tx.Commit();
        }

user1 和 user2 都有相同的登录值,但我在添加用户 2 之前删除了 user1。我在添加 user1 的行上放置了断点,我在 SQL Server Profiler 中看到,调用方法 Add() 时会立即添加行,但是当我调用 Delete() 时,它会被推迟;当调用 tx.Commit() 时,该行在 SQL 中被删除并导致此类异常:

NHibernate.Exceptions.GenericADOException: 'could not insert: 
[WCFService.DAL.UserEntity][SQL: INSERT INTO [User] (FirstName, LastName, 
Login, Password) VALUES (?, ?, ?, ?); select SCOPE_IDENTITY()]'

添加和删除方法是在通用存储库中实现的,下面我将向您展示代码:

public class GenericRepository<T> : IRepository<T> where T : class
{
    private readonly ISession _session;
    (...)
    public void Add(T entity)
    {
        _session.Save(entity);
    }

    public void Delete(T entity)
    {
        _session.Delete(entity);
    }

我试图在 Google 中找到为什么 NHibernate 会这样,但找不到解释。这是错误还是预期的行为?

尽管当我取消注释这一行时它会有所帮助:

    //_session.Flush(); unlocking this helps

但我认为应该更加一致:要么各种数据修改(添加、更新、删除)立即发生,要么在事务提交时发生。 难道我做错了什么?

查看文档9.6. Flush

会话始终按以下顺序执行 SQL 语句 (在刷新期间)

  • The SQL statements are issued in the following order

  • all entity insertions, in the same order the corresponding objects were saved using ISession.Save()

  • all entity updates

  • all collection deletions

  • all collection element deletions, updates and insertions

  • all collection insertions

  • all entity deletions, in the same order the corresponding objects were deleted using ISession.Delete()

所以,我们能做的,真的是调用 Delete 和 Flush,然后 Insert/Save。

如果我们混着用,就用上面的流程...总是