如何坚持更改Db上下文的跟踪信息并还原?

时间:2019-05-03 06:10:02

标签: c# ef-core-2.1 ef-core-2.2

  

我们必须检测数据库上下文内部的更改并安排数据库更新   以后。

如何将change tracker info of Db Context保留到临时数据库中,以便以后可以将它们还原到另一个DbContext实例中。

  

因此,仅在新建Db Context实例上执行.SaveChanges即可提交   待更改。

2 个答案:

答案 0 :(得分:3)

我可以想到两种解决方案:

  1. 将批准的字段添加到表中,并根据值过滤输出(使用视图仅读取批准的项目),删除未批准的记录。 (如果大多数请求都将得到批准并且不需要保留历史数据,则是合适的。)

  2. 复制服务器上的现有表(仅结构),这允许重新使用生成的EF类,称为请求。批准后,使用SQL查询将记录添加到主表,然后从“请求”表中删除该行。如果请求被拒绝,则可以将其添加到拒绝表中,提供拒绝的原因。

这些方法的优点:

  1. 由于所有操作都发生在同一数据库(而不是本地数据库或不同数据库)中,因此原子交易是可能的,并且可以使用现有的备份/恢复/可用性策略。

  2. (#2)可以创建历史记录以提供问责信息。

答案 1 :(得分:2)

也许您要做的就是拥有一个本地临时数据库,该数据库的结构与您的主(远程)数据库相同;然后将SaveChanges保存到本地数据库中,而不是保存到主数据库中。

要将SaveChanges定向到本地数据库而不是主数据库,只需在创建DbContext时使用其他连接字符串即可。 (尽管已经进行了一些讨论,可以更改DbContext上的连接,但是当前尚未实现,请参见https://github.com/aspnet/EntityFrameworkCore/issues/8494。)

所以...说您所做的更改是在“主” DbContext中,然后为本地数据库创建第二个DbContext,然后将更改从“主” DbContext.ChangeTracker复制到“本地” DbContext。 ChangeTracker。您可以通过遍历ChangeTracker条目来做到这一点,并:克隆实体(构造一个实体,并使用PropertyInfo.SetValue复制EntityEntry.OriginalValues中的所有值);将实体附加到“本地” DbContext;然后应用更改(使用EntityEntry.CurrentValues获取当前值,测试!EqualityComparer.Default.Equals,如果不相等,则再次使用PropertyInfo.SetValue应用当前值)。

如果您只需要浅表副本,这将非常简单;如果需要深层副本,则还需要浏览模型中的关系。

对于所有其他方法,另一种方法是始终将所有内容保存到本地数据库,然后使用单独的过程(例如批处理过程)将值复制到主数据库中。作为一般性评论,无论您如何执行此操作,都需要处理将本地值发送到主数据库时可能发生的任何并发冲突。

史蒂夫

P.S。还可以尝试使用DbContext.Database进行试验,以查看是否可以重定向连接-如果您愿意不使用“受支持的” API。