0

我有一个我经常遇到的场景。使用标准 ADO 事务很简单,但使用 NH(据我所知)就不那么简单了。

我有 2 个表要更新。第一个包含配置文件信息(Profile),另一个(Work)包含需要进行的记录更改以及这些更改的状态。对于 Profile 表的每次更新,Work 表上的状态都会更新。

  • 如果对 Profile 表的更新失败,我需要更新 Work 表的状态。
  • 如果 Profile 表更新成功,Work 表更新失败,我需要回滚事务。

问题是,在我提交事务之前,我不知道对 Profile 表的更新是否失败。我试图在 Profile 上执行 Flush 以捕获异常,以便将状态写入 Work 表,但随后我的 Commit 因 Profile 更新导致的异常而失败。

我该如何处理?在典型的 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() 不起作用,但我不知道该怎么做。

4

2 回答 2

0

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

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

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

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

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

于 2010-09-14T23:14:44.900 回答
0

我不认为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();
    }
}
于 2010-09-14T20:21:23.550 回答