繁体   English   中英

将库用户警告到不一致的状态

[英]Alerting Library Users to an Inconsistent State

在本机库上的托管包装器中,我必须完成某些操作,这些操作对于高级对象的用户应该被认为是原子的和一致的。 但是,本机代码中的基础操作是原子的并且是单独一致的,但不是整体的。

// Simplistic look at the AddRange operation
void AddRange(IEnumerable<ChildType> range)
{
    foreach (var value in range)
    {
        this.NativeAdd(value);
    }
}

// Simplistic look at the Delete operation
void Delete(ParentType value)
{
    foreach (var child in value.Children)
    {
        this.NativeDelete(child);
    }

    this.NativeDelete(value);
}

如果Native代码存在错误,则所有Native操作都会失败并显示常见的异常类型:

void NativeDelete(ChildType child)
{
    StatusCode status = StatusCode.NoError;
    NativeMethods.DeleteChild(this.id, child.Id, out status);

    if (status != StatusCode.NoError)
    {
        throw new LibraryException(this, child, status);
    }
}

在高级AddRange和Delete例程中,我遇到了一些本机Add或Delete调用已完成的情况,但其中一个调用发生错误,其余调用未完成。

更新:对于用户来说,如果他们添加了7个项目并且在第7个项目上失败了,或者如果他们成功添加了6个项目,则磁盘上的实际文件看起来不会有任何不同。 记录错误的唯一时间是在运行时。 因此,如果用户未意识到状态不一致的可能性,则他们可能无法确定基础文件是否有效。

我是不是该:

  1. 让LibraryException通过并向用户提供ParentType或ChildType对象可能处于不一致状态的文档
  2. 将LibraryException包装在InconsistentStateException中,该事件包含有关哪些对象可能处于不一致状态的信息
  3. 捕获LibraryException并尝试“重新”回滚所做的更改,然后重新抛出用户的异常(不是这个的粉丝)
  4. 别的什么?

没有真正的两阶段提交支持(即事务管理器),就不可能实现3。 如果发生错误,手动回滚只会导致更多的不一致状态。

我认为2是多余的。 如果在父类型上调用方法(这是这些方法公开的方法),并且在抛出该异常时发生异常,则假设对象上的状态已损坏(除少数例外) 。 通常,当发生这种情况时,您不能对该对象做很多事情,除非将其抛弃并使用具有一致状态的新对象。

留下1,记录它。 虽然您可能会在2中提供大量结构化信息,但如果对象处于不一致状态,您实际上并不想尝试修复该状态,因为您冒更大的风险。

我喜欢你的第二个选择 -

这将提供一个更有意义的例外,您可以控制它。 没有理由强迫你的最终用户理解一些奇怪的状态代码等。至少这样,很明显发生了什么以及为什么。

如果我正确理解您的更新,则调用者可以做的就是将信息传递给最终用户,最终用户必须决定是接受状态还是回滚。

在这种情况下,(2):提供所有信息,以便调用者可以将信息传递给用户,或日志文件,或一些统计数据,而无需大量工作。

(1)如果(2)没有信息差异,则可以,例如,知道哪个项目失败是无关紧要的。

(3)如果你不能指望在大部分时间里修复它是没有意义的,如果你有一点机会让它变得更糟,那就很危险了。

根据文件大小,您可以通过处理副本来进行准原子更改。 至少,用户可能期望一种简单的方法来回滚到上一次保存。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM