【问题标题】:EF.NET Core: Multiple insert streams within one transactionEF.NET Core:一个事务中的多个插入流
【发布时间】:2020-08-13 13:22:19
【问题描述】:

我有很多行(300k+)要在最短的时间内插入到 SQL Server 数据库中,所以我的想法是使用并行化和分区数据并使用异步将数据泵入 SQL,X 线程在时间,每个上下文 100 行,上下文被回收以最小化跟踪开销。但是,这意味着要并行使用多个连接,因此 CommittableTransaction/TransactionScope 将使用分布式事务,这将导致并行事务登记操作返回臭名昭著的 "This platform does not support distributed transactions." 异常。

我确实需要提交/回滚整个 upsert 集的能力。它是批量上传过程的一部分,任何错误都应将更改回滚到以前的工作/稳定条件,应用程序明智。

我有哪些选择?只用一个连接不并行化?

注意:问题并不像一批插入命令那么简单,如果是这样的话,我会生成插入并在服务器上运行它们作为查询或确实使用SqlBulkCopy。其中大约一半是更新,一半是插入,其中新键由 SQL Server 生成,需要获取并在接下来插入的子对象上重新设置键,行分布在 3 级层次结构中的大约十几个表中.

【问题讨论】:

  • 创建选项可以做的一件大事是从 IDENTITY 切换到序列以生成密钥。序列支持客户端键生成,因此您可以对整个对象图进行键控。然后,您可以按外键顺序批量加载或暂存/合并表。见docs.microsoft.com/en-us/sql/relational-databases/…
  • 有没有办法用表键来做到这一点并将其与IDENTITY_INSERT ON结合起来?
  • EF Core 支持序列,但它们在 SQL Server 中设置为列默认值,而不是 IDENTITY 列。因此,您可以根据需要提前生成密钥。 IDENTITY_INSERT 的问题(当然有几个),但这里最大的问题是无法提前生成键值。见docs.microsoft.com/en-us/ef/core/modeling/sequences
  • 这是一个很好的提示,谢谢,我一定会在以后的数据库中记住这一点。但是,这个不在我们的控制之下,它是一个生产数据库,并且模式更改是不行的,特别是因为有其他系统在使用它。风险管理会砍掉我的头:)

标签: c# sql-server entity-framework .net-core task-parallel-library


【解决方案1】:

不。完全错误的做法。不要为此使用 EF - 批量插入 ETL 不是对象关系映射器的用途,并且许多设计决策对此没有成效。您也不会使用小型汽车而不是卡车来运输 20 吨货物。

如果您以某种方式使用 SqlBulkCopy API,300k 行是微不足道的。

【讨论】:

  • 同意。了解您的工具集及其限制。 EF 虽然在很多方面都很出色,但在大规模数据集插入/更新方面并不那么出色。不要害怕在需要时使用一些实际的 SQL。
  • EF 让我保持强输入,考虑到我必须忍受的一切,我会尽我所能提供帮助。问题并不像一批插入命令那么简单,如果是这样的话,我只会生成插入并在服务器上运行它们作为查询。其中大约一半是更新,一半是需要获取新键并在子对象上重新设置键的插入,行分布在 3 级层次结构中的大约十几个表中。 SqlBulkCopy 对我帮助不大,只是增加了一层魔术字符串的复杂度。
  • 我在大约半天的时间里围绕 SqlBulkCopy 编写了一个强类型映射器——所以这不是借口。在插入之前将其加载到临时表(这就是我所做的)中也很简单。没有魔法字符串,所有这些都基于反射和 Ef 使用的属性;)
  • @mmix - 这是 EF 的一大优点,让您保持强类型。但是你会遇到很多问题,试图让 EF 在一些“高性能”时间内完成 300K 行。你见过/调查过 SQL 中的 MERGE 语句吗? docs.microsoft.com/en-us/sql/t-sql/statements/…
  • EF 核心也进行批处理。它不是 SqlBulkCopy,但您至少应该测试单 DbContext 天真的 EF 方法。另一种选择是将对象图作为 JSON 发送到 SQL 并运行从 JSON 读取的 INSERT/MERGE 查询。但无论如何,从多个客户端会话运行不太可能有帮助。
猜你喜欢
  • 1970-01-01
  • 2011-01-08
  • 1970-01-01
  • 2012-11-20
  • 2016-05-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-16
相关资源
最近更新 更多