1

我有一个数据输入 ASP.NET 应用程序。在一个完整的数据输入期间,会发生许多事务。我想跟踪所有这些交易,以便如果用户想放弃数据输入,我一直记录的所有交易都可以回滚。

SQL 2008,框架版本为 4.0,我使用的是 c#。

4

4 回答 4

5

对于刚接触 Web 开发的人来说,这始终是一个艰难的教训。但这里是:

每个往返 Web 请求都是一个单独的、独立的执行线程

这意味着,简单地说,每次您提交页面请求(单击按钮,导航到新页面,甚至刷新页面)时,它都可以在与前一个不同的线程上运行。更重要的是,即使您确实获得了两次相同的线程,在您两次请求之间的时间内,该线程可能已经处理了其他几个 Web 请求。

这使得跨越多个 Web 请求的简单事务实际上是不可能的。

这是您应该记住的另一个概念:

事务旨在用于批处理操作,而不是交互式操作。

这意味着事务是短暂的,并且包含几个按顺序(或同时)执行的操作,其中所有操作都是原子的,并且旨在全部完成或全部失败。事务通常不设计为长期存在的(意味着等待用户以交互方式决定各种操作)。

Web 应用程序不是桌面应用程序。 他们不像他们那样运作。当你做网络应用时,你必须改变你的想法。最大的教训是,每个请求都是一个独立的执行单元。

现在,在上面,我说的是“简单事务”,也称为轻量级或本地事务。还有所谓的分布式事务,使用这些需要分布式事务协调器。MSDTC 非常常用。但是,DT 的执行速度比 LWT 慢得多。此外,他们要求将基础设施设置为使用 DTC。

可以使用 DTC 跨越 Web 请求上的事务。这是通过在分布式事务中“登记”来完成的,然后以某种方式在请求之间共享此事务标识符。但这需要大量的设置和处理工作,并且有很多容易出错的情况。如果您有其他选择,这不是您想做的事情。

一般来说,最好将数据添加到一个或多个临时表中,然后在最终保存完成后,将该数据传输到永久表中。另一种选择是维护一些状态(例如使用 ViewState 或 Session)来跟踪更改。

一种流行的方法是使用 JavaScript 在客户端执行操作,然后在完成后将所有更改提交给服务器。但是,如果您需要导航到不同的页面,这很难实现。

于 2012-10-13T06:18:02.000 回答
1

从您的问题来看,当用户行使回滚选项时,事务似乎已完成。在这种情况下,我怀疑 DBMS 的事务回滚语义是否可用。因此,我将在应用层提供如下语义:

  1. 任何可以对数据库执行的原子操作都应该封装在一个Command对象中。每个命令都将实现 undo 方法,该方法将恢复其 execute 方法执行的操作。
  2. 每个事务将包含作为其一部分运行的命令列表。事务按原样保留,以供将来进一步操作。
  3. 将向用户提供一种查看这些可能被回滚的事务的方法。在用户选择一个事务以将其回滚时,检索与该事务对应的命令列表,并在所有这些命令对象上调用 undo 方法。

HTH。

于 2012-10-13T06:16:59.420 回答
0

如果您只是在单个保存操作期间管理事务,请使用TransactionScope. 但听起来情况并非如此。

如果用户可能希望放弃n之前的保存操作次数,则表明该项目可能以草稿形式存在。可能有一份或多份工作草案。随后,必须有一种方法可以隐式或显式地将草案提升为最终版本。想想电子邮件程序如何保存草稿。它实际上并没有发送您的消息,您可以随时放弃它,并且您可以稍后再回忆它。当您发送消息时,您已经“提交了事务”。

您还可以添加用户界面以回滚到特定版本。

这将是相当多的工作,但如果您愿意保存和管理同一项目的多个副本,则可以完成。

您可以使用状态标志将相同数据的副本保存在同一模式中以指示它是草稿,或者您可以将数据以中间格式存储在单独的表中。我更喜欢第一种方法,因为它允许使用相同的结构。

于 2012-10-13T06:26:43.730 回答
0

您还可以将它们存储在临时表中,并在“稍后阶段”将这些记录移动到原始表中。

于 2012-10-13T06:31:31.367 回答