在活动事务中执行 Flush()

发布于 2024-09-19 11:16:17 字数 978 浏览 12 评论 0原文

我有一个经常遇到的场景。做起来很简单 标准 ADO 事务,但与 NH 不太一样(据我所知)。

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

  • 如果更新Profile表失败,我需要更新 工作表上的状态。
  • 如果Profile表更新成功,则更新 工作表失败,我需要回滚事务。

问题是我不知道是否更新了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() 不起作用,但我不知道还能怎样 来做到这一点。

I have a scenario that I commonly run into. It's simple to do with a
standard ADO Transaction, but not so much with NH (that I know of).

I have 2 tables to update. The first contains profile information
(Profile) and the other (Work) contains records changes that need to
be made and the status of those changes. For each update to the
Profile table, there will be an update to the status on the Work
table.

  • If the update to the Profile table fails, I need to update the
    status on the Work table.
  • If the update to the Profile table succeeds, and the update to the
    Work table fails, I need to rollback the transaction.

The problem is that I don't know if the update to the Profile table
failed until I commit the transaction. I tried to do a Flush on the
Profile to catch the exception so I could write the status to the Work
table, but then my Commit fails with the exception caused from the
Profile update.

How can I handle this? In a typical ADO Transaction, my first call
will throw, but I can catch and still update the other tables in the
transaction.

Here's sort of what my code looks like - pretty standard. This is not
my actual code, so please focus on the problem, not that I'm not
disposing my transaction or closing my session ;) :

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

}

I realize that Flush() is not going to work, but I don't know how else
to do this.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

清秋悲枫 2024-09-26 11:16:17

需要对您的要求进行一些澄清。

1)>>如果对配置文件表的更新成功,并且对工作表的更新失败,我需要回滚事务

我本来认为工作就像审计跟踪更新,如果配置文件更新有效,则不应失败。如果是这种情况,那么您不应该回滚您的事务。然而,话虽如此,您的代码已经符合此要求。

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

如果更新失败,那么您将回滚您的事务。除非您有两个单独的事务(一个用于配置文件和工作(当前),另一个仅用于工作),否则您将无法更新工作表。这对你来说有意义吗?

Some clarifications needed on your requirements.

1) >> If the update to the Profile table succeeds, and the update to the Work table fails, I need to rollback the transaction

I would have thought that Work is like an audit trail update and should not have failed if Profile update works. If this is the case, then you should not rollback your transaction. However, having said this, your code already comply to this requirement.

2) >>If the update to the Profile table fails, I need to update the status on the Work table.

If update fails, then you would have rolled back your transaction. You will not be able to update the Work table unless you have two separate transactions (one for both Profile and Work (as current) and then a separate one just for Work). Does this make sense to you?

辞别 2024-09-26 11:16:17

我认为在刷新之前进行 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();
    }
}

I don't see a problem with having a trans.Commit prior to the flush. Here's an example (slightly modified too look like yours):

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();
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文