我有一个应用程序将大量数据加载到内存中(这是因为它需要对大数据集执行一些数学模拟).这些数据来自几个数据库表,它们都是相互引用的.
数据的一致性规则相当复杂,查找所有相关数据需要对数据进行相当多的哈希和其他附加数据结构.
问题是用户还可以在对话框中以交互方式更改此数据.当用户按下OK按钮时,我想执行所有检查以确定他没有在数据中引入不一致.实际上,所有数据都需要立即检查,因此我无法逐步更新数据集并逐个执行检查.
但是,所有检查代码都在加载到内存中的实际数据集上工作,并使用散列和其他数据结构.这意味着我必须做以下事情:
我不喜欢这个解决方案,因为其他线程也在不断使用数据集,我不想在执行检查时暂停它们.此外,撤销意味着需要搁置旧情况,这也是不可能的.
另一种方法是单独从数据集中检查代码(并让它工作在明确给出数据,例如从对话框来),但是这意味着该检查代码不能使用散列和其它额外的数据结构,因为它们只在工作大数据集,使检查更慢.
在将复杂数据应用于"应用程序"数据集之前检查用户对复杂数据的更改有什么好的做法?
现在这可能没有太大帮助,因为您的应用程序已构建,并且您可能不想重新实现,但我会提到它以供参考。
使用 ORM 框架会对您有所帮助。它不仅可以将数据库中的数据转换为面向对象的表示形式,还提供了实现隔离临时更改和视图的工具:
使用带有事务的 ORM 框架,您可以允许用户更改模型中的对象,而不会影响其他用户,并且在检查数据之前无需“真正”提交数据。事务的 ACID 保证确保您的更改不会持久保存到数据库中,而是保存在事务中,只有您自己可见。然后,您可以对数据进行检查,并仅在数据验证时才提交事务。如果数据未验证,则回滚事务并放弃更改。如果它确实有效,您就提交事务并且更改将永久生效。
或者,您可以创建提供数据进行验证的视图。这些视图结合了基础数据和临时表(当前连接的本地表)。这避免了锁定表,但代价是必须编写和维护视图。
编辑:如果内存中已经有丰富的对象模型,那么支持增量、本地和隔离更改的最困难部分是对象之间的直接引用。当您想用包含更改的 A' 替换对象 A 时,您不想使用所有引用进行深层复制,因为您提到您的对象模型很大。另外,您不想更新所有指向 A 的对象以引用 A'。作为一个例子,考虑一个非常大的双向链表。不可能创建一个与旧列表相同的新列表,只更改一个元素,而不复制整个列表。您可以通过存储相关对象的标识符而不是对象本身来实现隔离。例如,您的协作者不是显式引用 A,而是存储对标识 A 的唯一键 key(A) 的引用。该键用于在需要时(例如在验证期间)获取实际对象。然后,您的模型将成为对象键的大型映射,可以针对本地更改进行装饰。通过键查找对象时,首先检查本地映射是否有值,如果没有找到,则检查通用映射。要将 A 更改为 A',您需要向本地映射添加一个条目,将 key(A) 映射到 A'。(请注意,A 和 A' 具有相同的密钥,因为逻辑上它们是相同的项目。)当您运行验证代码时,本地更改将被合并,因为引用密钥(A)的对象将获得 A',而其他用户使用 key(A) 将得到原始的 A。
这听起来可能很复杂,但通过删除显式引用并按需计算它们是支持独立更新而无需进行数据深层复制的唯一方法。
另一种但等效的方法是,验证器在使用对象之前使用映射来查找对象及其替换对象。例如,您的用户修改了 A,因此您将 A->A' 放入映射中。验证器正在迭代模型并遇到 A。在使用 A 之前,它会检查映射并找到 A',然后使用它。这种方法的困难在于,您必须确保每次使用对象之前都检查地图。如果你错过了一个,那么你对模型的看法就会不一致。
| 归档时间: |
|
| 查看次数: |
434 次 |
| 最近记录: |