用于预览用户更改并允许在一段时间内回滚/提交的解决方案

时间:2011-01-18 14:54:50

标签: asp.net sql-server linq-to-sql transactions session-state

在我尝试解决问题时,我已经问过few questions today

我们有一个复杂的数据结构,其中所有各种实体都紧密相连,几乎所有实体都严重依赖/依赖于其他类型的实体。

该项目是一个网站(MVC3,.NET 4),所有逻辑都是在业务层使用LINQ-to-SQL(2008)实现的。

我们需要做的是让用户在进行更改时“锁定”系统(还有其他原因,我不会在这里与数据库相关)。当该用户进行更改时,我们希望能够向他们显示他们正在更新的实体的原始状态,以及他们所做的更改的“预览”。完成后,他们需要能够回滚/提交。

我们考虑过这些选择:

  1. 持有一段交易,用户花费很长时间进行多项更改,这样才能完成。
  2. 将所有数据的副本保存在内存中(或缓存到磁盘)是一种选择,但它有很多,所以似乎不合理。
  3. 维护一组辅助表,或尝试使用会话状态存储更改,但这很复杂且难以维护。
  4. 使用两个数据库,通过连接字符串在它们之间翻转,并使用T-SQL管理复制,在提交/回滚后将它们重新同步。即打开/关闭,强制拍摄快照,反转方向等。
  5. 我们有点难以找到一个相对容易维护的解决方案。有什么建议吗?

4 个答案:

答案 0 :(得分:1)

我们对类似问题的解决方案是使用一个锁定表来保存系统中每个实体类型的锁。当客户端应用程序想要编辑实体时,我们执行“GetWithLock”,它为客户端提供实体数据的最新版本以及获取锁定(存储在锁定表中的GUID以及实体类型和实体ID)。这可以防止其他用户编辑同一个实体。使用更新提交更改时,通过从锁定表中删除锁定记录来释放锁定。由于存储过程是我们用于与数据库交互的API,因此可以非常直接地锁定/解锁对特定实体的访问。

在客户端,我们在UI模型类上实现IEditableObject。我们的模型类包含对在服务调用上检索的服务实体实例的引用。这允许UI执行开始/结束/取消编辑,并根据需要执行提交或回滚。通过保存原始服务实体的实例,我们可以看到原始数据和当前数据,这将允许用户获得您正在寻找的“预览”。

虽然我们的解决方案没有实现LINQ,但我不相信我们的方法中有任何独特的东西会妨碍您使用LINQ。

HTH

答案 1 :(得分:0)

考虑一下:

  1. 长事务会降低系统的可扩展性。如果执行UPDATE命令,则会在提交/回滚之前更新锁定,从而阻止其他事务继续进行。
  2. 第二个表/数据库可以通过concurent事务修改,因此您不能依赖表中的数据。唯一的办法是锁定它=>见no1。
  3. 某些数据引擎中的可序列化事务使用表中的数据版本。因此,在执行第一个cmd之后,事务可以在cmd执行时间内看到可用的确切数据。这可能有助于您显示用户所做的更改,但您无法保证将其保存回存储。
  4. DataSet包含旧版/新版数据。但不幸的是,这不符合您的技术目标。

答案 2 :(得分:0)

使用一组辅助表格。

问题是您的连接应该看到两个版本的数据,而其他连接只能看到一个(或两个,其中一个是他们自己的)。

虽然理论上可以并且使用闪回在Oracle中实现,但SQL Server本身不支持它,因为它无法查询以前版本的记录。

您可以发出如下查询:

SELECT  *
FROM    mytable
AS OF TIMESTAMP
        TO_TIMESTAMP('2010-01-17')

Oracle但不在SQL Server

这意味着您需要自己实现此功能(将新版本的行放入您自己的表中)。

答案 3 :(得分:0)

听起来像一个丑陋的问题,并提出了很多你无法在SO上提出的问题。我在阅读你的问题时得到了以下想法,虽然它“闻起来”和你列出的其他人一样糟糕,但它可以帮助你制定最终的解决方案。

首先,如@ user580122所述,使用某种锁定系统来标记/记录其中一个事务正在进行的事实。 (务必包括某种定期的自动检查,以测试丢失或遗弃的交易!)

接下来,对于您对数据库所做的每一项更改,都要以某种方式记录它,无论是在应用程序中还是在某个专用表中。这个想法是,给定X状态下数据库的副本,您可以随时重新运行用户提交的步骤。

接下来要弄清楚如何使用数据库快照。在BOL中阅读这些内容;一般的想法是你创建一个数据库的时间点快照,做任何你想做的事情,并最终扔掉它。 (仅适用于SQL 2005及更高版本,仅适用于企业版。)

所以:

  • 用户出现并启动其中一个元交易。
  • 数据库中标记了一个标志,显示正在进行的操作。如果已经在进行中,则无法启动新事务。 (再次,偶尔检查丢失的交易!)
  • 对数据库所做的每一次更改都会以可重复的方式进行跟踪和记录。
  • 如果用户决定取消该交易,您只需删除快照,并且不会更改任何内容。
  • 如果用户决定保留该事务,则删除该快照,然后立即将记录的更改重新应用于“真实”数据库。这应该有效,因为您的要求意味着,当有人正在处理其中之一时,没有其他人可以触及数据库的相关部分。

是的,这肯定闻起来,它可能不适用于您的问题。希望这里的想法可以帮助你解决问题。