我有一个过程正在导入 Excel Spreadhseet,并将数据解析为我的数据对象。该数据的来源是 非常 这是值得怀疑的,因为我们正在将客户从基于电子表格的数据管理转移到可检查有效数据的托管数据库系统。

在导入过程中,我对数据进行了一些基本的完整性检查,以适应我们导入的数据可能有多糟糕,但我的整体验证是在 DbContext 中完成的。

我想做的一部分是,我想在电子表格中提供数据错误的行号,以便他们可以轻松确定需要修复哪些内容才能导入文件。

一旦我从电子表格中获得数据(model),以及他们正在使用的数据库中的机会(opp),这是我的过程的伪代码:

foreach (var model in Spreadsheet.Rows) { // Again, pseudocode
    if(opp != null && ValidateModel(model, opp, row)) {
        // Copy properties to the database object

        // This is in a Repository-layer method, not directly in my import process.
        // Just written here for clarity instead of several nested method calls.
        context.SaveChanges(); 
    }
}

如果需要,我可以在此处提供更多代码,但问题出在我的 DbContext 中 ValidateEntity() 方法(DbContext 的重写)。

再说一遍,据我所知,我编写的代码没有任何问题,但如果机会未通过此级别的验证,那么它会作为未保存对象的一部分保留在 context, ,这意味着它每次都会重复尝试进行验证 ValidateEntity() 叫做。这会导致在发生初始问题后每行重复出现相同的验证错误消息。

有没有办法[编辑]让 Context 在验证失败一次后停止尝试验证对象[编辑]?我知道我可以等到最后再打电话 context.SaveChanges() 最后一次来解决这个问题,但我希望能够将其与数据库中的行相匹配。

作为参考,我使用 Entity Framework 6.1 和 Code First 方法。

编辑 试图为 Marc L 进一步澄清。(包括对上面代码块的更新)

现在,我的流程将迭代电子表格中尽可能多的行。我为什么要调用存储库层来保存每个对象,而不是使用仅调用的方法 context.SaveChanges() 一次是让我自己能够确定哪一行是导致验证错误的行。

我很高兴我的 DbContext 是自定义的 ValidateEntity() 方法正在捕获验证错误,但问题在于它没有抛出 DbEntityValidationException 对于同一实体多次。

我希望如果对象验证失败一次,上下文就不再尝试保存对象,无论多少次 context.SaveChanges() 叫做。

有帮助吗?

解决方案

你的问题不是一个骗局(这是关于保存,而不是加载实体),但你可以遵循吉米上面的建议。也就是说,一旦将实体添加到上下文中,就会在“已添加”状态下对其进行跟踪,并且阻止其重新验证的唯一方法是分离它。这是一个 SO 内部链接,但我将重现代码片段:

dbContext.Entry(entity).State = EntityState.Detached;

但是,我认为这不是您想要的方式,因为您不必要地使用异常来管理状态(异常非常昂贵)。

根据给定的信息,我会使用更基于集合的解决方案:

  • 修改模型类,使其包含记录原始电子表格行的 RowID(可能还有其他很好的理由这样做)
  • 关闭上下文的实体跟踪(轮流变化检测允许每个 Add() 为 O(1))
  • 添加所有实体
  • 称呼 context.GetValidationErrors() 并立即获取所有错误,使用前面提到的 RowID 来识别无效行。

您没有指出您的进程是否应该保存好行或拒绝整个文件,但这将适应其中任何一个 - 也就是说,如果您需要保存好行,请使用上面的代码分离所有无效行并然后 SaveChanges().


最后,如果您确实想保存好的行并且对基于集合的方法感到不舒服,那么最好使用新的 DbContext 对于每一行,或者至少创建一个新的 DbContext 每次错误之后。ADO.NET 团队坚持认为上下文创建“相对便宜”(抱歉,我手头没有这方面的引用或统计数据),因此这不会对您的吞吐量造成太大影响。即便如此,它至少仍会保持 O(n)。我不会责怪你,管理大环境也会让你面临其他问题。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top