是否有在 Entity Framework/EF Core 中进行大规模图克隆操作的策略或设计模式?

Posted

技术标签:

【中文标题】是否有在 Entity Framework/EF Core 中进行大规模图克隆操作的策略或设计模式?【英文标题】:Is there a strategy or design pattern for making large-scale graph clone operations in Entity Framework/EF Core? 【发布时间】:2016-12-19 11:30:03 【问题描述】:

从本质上讲,我们有一个具有重复 template 模式和该模板的 instances 的数据库。模板无限期地存在,而实例是及时绑定的。一组用户仅使用模板,一组用户仅使用连接到实例的“答案”实体。当对模板进行更改时,当前处于活动状态的实例会自动接收来自模板的更改(包括克隆相关实体或使现有克隆同步),而较旧的实例“在您离开它们时”保持不变,即为了不追溯更改历史记录的绝对要求。当您回到 2013 年时,您希望查看截至 2013 年最后一次更改时的最新数据,而不是更新的数据。因此克隆。

这一切听起来都不错,只是制作克隆涉及克隆涉及的实体图,有时包括多对多关系。确保使用刚刚更新的模板版本的信息涉及传递特定的尚未保存的实体对象或在每一步保存,忘记所有对象并每次创建新上下文。这段代码很难编写,更难写好,维护起来简直就是一场噩梦。

我一直在拼命寻找合适的文献,甚至找不到关于数据库建模模式的文章(或就此而言更好的替代方案),更不用说在 EF 中做些什么来尽可能高效地工作.我是否遗漏了什么,或者这只是一个具有固有复杂性的问题?

【问题讨论】:

对我来说这“太宽泛了”。您应该提供一个示例来演示您尝试解决的主要问题,EF 中的克隆可能非常简单(只需 Add() 一个对象图根),但我无法从您的描述中拼凑出这将如何适应。 【参考方案1】:

没有任何内置功能可以帮助解决这种特定情况。我会考虑一个基于反射和实体框架元数据模型的解决方案来自动化很多。这样也更容易做对。

对象的克隆图应该是可自动化的,并且几乎没有固有的复杂性。但是,如果您只想克隆特定部分,我可以很容易地看到复杂性蔓延。这可能是固有的复杂性。另一方面,如果您发现自己编写相同的克隆代码并到处复制循环,那就是错过了抽象并且是人为的复杂性。

确保使用刚刚更新版本的模板的信息涉及传递特定的尚未保存的实体对象或在每一步保存,忘记所有对象并每次创建新的上下文。

我不太明白你在这里的意思。但是谈论多个上下文让我非常警觉,因为这是一种常见的反模式。通常,您希望每个逻辑工作单元有一个上下文。通常,该 UOW 是 HTTP 请求或 WCF 请求或用户交互。当所有实体都属于同一上下文时,许多问题就会消失。

此外,没有必要不保存对象。通常,数据库应该与内存中的实体状态同步。因此,当您在模板克隆过程中创建新对象时,没有理由不保存它们。没有必要在每个新实体之后保存。出于性能原因,请尽量不要过于频繁地保存。

如果您详细说明具体问题,我可以添加评论。

【讨论】:

关于许多上下文,我主要指的是this issue,您不能轻易地“重新查找”添加到数据库集中的对象。由于我们正在尝试创建融合的“创建或更新”方法,因此此问题出现的频率比您想象的要多。在 EF6 中,我们在每个集合上都有 .Local 来解决这个问题。我们目前正在尝试使用 EF Core,但可能必须转到 EF6 才能获得足够的功能。 我们已经尝试了自动化水平,这似乎是可能的解决方案,但是我们也有绝对不应该被克隆的关系,正如你所说的那样使事情复杂化。当前的解决方案至少包含足够的内容,只能以一种方式、一种方法填充克隆,并且只有“一个循环”。我见过一两个基于反射的克隆示例,但除了非常简单的父子数据或处理“更新插入”克隆(即更新现有克隆)之外,没有任何迹象表明正在测试。 “保存中点”解决问题的一个具体示例是法律实体与多个 LawCategory 实体(多对多)的关系已更改。首先,实体被更新,多对多表的条目也被更新。但是在 update-all-the-clones 阶段,如果没有保存,抽象的 clone-many-to-many 逻辑无法在现有上下文中看到这些新条目,因为它试图从多对多表的实体 dbset 直接。 (续...) (续)如果它可以通过实体对象本身的关系集合,则不需要这样做,但 EF Core 不允许延迟加载,这会给我们带来额外的负担以确保我们通过其余代码所期望的正确关系/数据库集来更新这些条目。但是我们也不想依赖“保存中点”,以防我们在某个时候会有一组暂时无效的数据。 是的,能够“看到”新实体是保存的好理由。您甚至可以采用模式在创建实体后始终保存。延迟加载的集合是有问题的,因为它们可能会过时(实体类型的标量属性不会过时,因为您正在写入它们)。我根本不使用实体集合。我总是写一个查询。而不是使用 Local 我建议根本不依赖集合导航属性。通常,无论如何,您都需要一些过滤器、加入或订购。导航集合无法在数据库中执行任何操作。

以上是关于是否有在 Entity Framework/EF Core 中进行大规模图克隆操作的策略或设计模式?的主要内容,如果未能解决你的问题,请参考以下文章

微软发布 Entity Framework EF Core 8 或 EF8

Entity Framework EF 代码首先使用 ExecuteStoreCommand 执行 sproc 非常慢

csharp: NHibernate and Entity Framework (EF) (object-relational mapper)

[C#/.NET]Entity Framework(EF) Code First 多对多关系的实体增,删,改,查操作全程详细示例

.NET Entity Framework(EF)使用SqlQuery直接操作SQL查询语句或者执行过程

是否有在 Android 上创建选项卡式布局的声明性方式?