【问题标题】:Doing Flush() inside active Transaction在活动事务中执行 Flush()
【发布时间】:2010-09-14 18:22:39
【问题描述】:

我有一个我经常遇到的场景。这很简单 标准的 ADO 事务,但与 NH(据我所知)没有那么多。

我有 2 个表要更新。第一个包含个人资料信息 (Profile) 和另一个 (Work) 包含需要更改的记录 以及这些更改的状态。对于每次更新 Profile 表,Work 上的状态会有更新 表。

  • 如果更新配置文件表失败,我需要更新 工作台上的状态。
  • 如果对 Profile 表的更新成功,并且对 工作表失败,我需要回滚事务。

问题是我不知道是否更新到 Profile 表 在我提交交易之前失败。我试图做一个冲洗 配置文件以捕获异常,以便我可以将状态写入工作 表,但随后我的 Commit 因异常而失败 个人资料更新。

我该如何处理?在典型的 ADO 事务中,我的第一次调用 会抛出,但我可以捕捉并仍然更新 交易。

这是我的代码的样子 - 非常标准。这不是 我的实际代码,所以请关注问题,而不是我不是 处理我的交易或关闭我的会话;):

try
{
    ITransaction trans = _session.BeginTransaction();

    var work = _repo.GetWork();
    var profile = _repo.GetProfile(work.ProfileId);

    try
    {
        profile.UpdateWithNewValues(work);
        _session.SaveOrUpdate(profile);
        _session.Flush();
        work.Status = "Success";

    }catch{
      work.Status = "Failure";
    }

    _session.SaveOrUpdate(work);
    trans.Commit();

}catch{

    trans.Rollback();

}

我意识到 Flush() 不起作用,但我不知道还有什么办法 这样做。

【问题讨论】:

    标签: nhibernate transactions flush


    【解决方案1】:

    需要对您的要求进行一些说明。

    1)>>如果更新Profile表成功,更新Work表失败,需要回滚事务

    我会认为 Work 就像一个审计跟踪更新,如果 Profile 更新有效,应该不会失败。如果是这种情况,那么您不应该回滚您的事务。但是,话虽如此,您的代码已经符合此要求。

    2) >>如果更新Profile表失败,我需要更新Work表的状态。

    如果更新失败,那么您将回滚您的事务。您将无法更新 Work 表,除非您有两个单独的事务(一个用于 Profile 和 Work(作为当前),然后一个单独的仅用于 Work)。这对你有意义吗?

    【讨论】:

    • 是的,我意识到这一点,但希望得到一个更简单的答案。这实际上是针对批处理的,因此我省略了相关的细节。感谢您的建议。
    【解决方案2】:

    我认为在刷新之前使用trans.Commit 没有问题。这是一个示例(稍作修改也看起来像您的):

    Profile profile;
    Work work;
    ITransaction tx;
    
    try
    {
        session.SaveOrUpdate(profile);  
    
        work.Status = "Success";    
        session.SaveOrUpdate(work);
    
        tx.Commit();
    }
    catch (Exception)   // wroh oh...
    {
        try
        {
            work.Status = "Failure";
            session.SaveOrUpdate(work);
    
            tx.Commit();
        }
        catch (Exception)
        {
            if (!tx.WasRolledBack)
            {
                tx.Rollback();
                session.Clear();
            }
    
            throw;
        }
    }
    finally
    {
        if (session.IsOpen)
        {
            // Whatever happened, Flush/Persist at the end.
            session.Flush();
        }
    }
    

    【讨论】:

    • 感谢您的想法,但由于几个原因,这行不通。首先,如果第二个事务失败,我将无法回滚第一个事务。其次,一旦出现异常,事务就会保留它以供任何进一步的 commit() 调用。
    猜你喜欢
    • 2014-02-26
    • 2021-11-13
    • 1970-01-01
    • 2014-07-25
    • 2014-10-10
    • 2012-12-21
    • 2011-11-06
    • 2022-08-18
    • 2016-01-08
    相关资源
    最近更新 更多