我们正在创建一个允许用户为其客户创建和修改账单的系统。这些修改需要作为审计目的的法案的一部分来维护。它在某种程度上是一个时间点架构,但我们不是仅仅通过修订来追踪。这是一个ASP.NET MVC 5,WebAPI2,EntityFramework 6,在客户端和服务器上使用Breeze的SQL Server应用程序。
我正在试图找出如何让Breeze和我们的数据模型正常工作。当我们修改实体时,我们基本上保留旧行,使用修改制作它的副本并更新一些实体状态字段w / date / time / revision number等。我们总是可以根据实体ID和EditState字段获取最新版本的实体,其中“1”是最新的。
我制作了一个小样本应用程序,以便让Breeze作为解决方案的一部分工作,并在客户端上启用一些不错的SPA架构和内联编辑,这一切都有效...除了因为我们的实体框架代码自动创建一个包含修改的新实体,SaveChanges响应包含原始实体但不包含新的“更新”实体。重新加载客户端上的数据是可行的,但除了为了演示目的而进行黑客攻击之外,这样做当然是愚蠢的。
所以我创建了一个新的ContextProvider并继承自EFContextProvider,覆盖了AfterSaveEntities方法,然后事情变得有点复杂。并非所有实体都具有此“时间点”/修订功能,但大多数实体都具有此功能。如果他们这样做我可以如上所述使用其EntityId和EditState获取该实体的最新版本,但我没有看到获得新实体的直接方式(对于EF来说很新,对Breeze来说很新)所以我'我希望能在这里找到一些指示。
这个解决方案是否位于Breeze或我们的DataContext中?我可以做一些反思,获取类型,查询更新的实体并将其推入saveMap。这似乎可能会在某些时候崩溃(不确定如何或何时,但似乎粗略)。我们的架构坏了吗?我们是否应该创建审计/日志表以存储修改后的值,而不是通过将实体的所有修订保留在其原始表中但使用修订信息并使查询稍微复杂一些来保持数据模型更小?我只是在EF中遗漏了一些东西吗?
...并且对于明显的回应,我知道我们应该使用文档数据库,但这不是该项目的选项。我们陷入了关系之地。
答案 0 :(得分:2)
我没有试过这个,但另一种方法是简单地将BeforeSaveEntities方法中传入实体的EntityState从Modified更改为Added。您可能还需要更新此“新”实体中的某个版本字段,以使其与原始实体没有主键冲突。
但是......过去曾经建立过这样的应用程序,我真的推荐另一种方法。将每种类型的“历史”实体存储在单独的表中。它可以与“当前”表格完全相同。当您保存时,首先将“当前”实体复制到“历史”表中(再次使用主键的某些版本编号或日期架构),然后正常更新“当前”实体。
答案 1 :(得分:0)
这可能不会给你你想要的答案,但这是一个想法:
保存对象时,拦截保存在服务器上,获取需要修改的对象实例,从具有相同ID的数据库中读取对象,将该旧对象的副本放入数据库中的旧表并继续保存进入主表。这样,只有最新版本保留在主表中,而旧表将包含所有以前的版本。
因此,您需要做的就是有两个包含相同对象的表:
public DbSet<MyClass> OriginalMyClasses{get;set;}
public DbSet<MyClass> LegacyMyClasses{get;set;}
当进入E状态为Modified时,覆盖SaveChanges函数和拦截,读取E类型,获取原始表和旧表,从具有相同ID的E读取对象O,将O保存到Legacy表,最后返回base.SaveChanges( ); (让它默认保存)。