c# - 如何改进 Entity Framework 批量插入

标签 c# sql entity-framework insert bulkinsert

我有一个从多个套接字接收数据然后将数据写入数据库的应用程序。

我目前正在使用 EF 来执行此操作。我想知道如何让它更有效率。

我读到过批量插入速度更快,所以我每 500 次插入才将更改保存到数据库:

   db.Logs_In.Add(tableItem);
            if (logBufferCounter++ > 500)
            {
                db.SaveChanges();
                logBufferCounter = 0;
            }

现在我已经分析了应用程序,74% 的工作由函数完成:System.Data.Enitity.DbSet'1[System._Canon].Add

有没有更好的插入方式?也许将 tableItems 排队到一个列表中,然后将整个列表添加到数据库上下文中。

或者也许我看错了,我应该完全避免使用 EntityFramework 来实现这种更高性能的插入?目前它是我的应用程序中的瓶颈,如果我查看系统资源,SQL 似乎连眼皮都没动一下。

所以我的问题:

1:我将以何种方式在多个插入中实现最高效/最快的插入

2:如果 EF 可以接受,我该如何改进我的解决方案?

我使用的是 SQL Server 2012 企业版, 传入的数据是一个恒定的流,但是我可以缓冲它,如果这是更好的解决方案,然后执行批量插入。

[编辑]

进一步解释场景。我有一个在 concurrentQueue 上循环的线程,它使该队列中的项目出队。然而,由于数据库插入是瓶颈这一事实。队列中通常有数千个条目,因此如果还有一种异步或并行方式,我可能会使用多个线程来执行插入操作。

最佳答案

对于涉及大量插入的场景,我倾向于“单独缓冲”(内存中,或 redis 列表,或其他),然后作为批处理作业(可能每分钟,或每隔几分钟)读取列表和使用 SqlBulkCopy尽可能有效地将数据放入数据库。为了解决这个问题,我使用了 ObjectReader.Create fastmember的方法,它公开了一个 List<T> (或任何 IEnumerable<T> )作为 IDataReader可以输入 SqlBulkCopy , 公开 T 的属性作为数据阅读器中的逻辑列。然后,您需要做的就是填写 List<T>来自缓冲区。

但是请注意,您需要考虑“出现问题”的情况;即,如果插入中途失败,您将如何处理缓冲区中的数据?这里的一种选择是执行 SqlBulkCopy进入一个staging 表(相同的架构,但不是“实时”表),然后使用常规 INSERT当您知道数据在数据库中时,一步复制数据 - 这使恢复更简单。

关于c# - 如何改进 Entity Framework 批量插入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24882766/

相关文章:

C# 变量名转字符串

mysql - 获取具有特定 revision_status 的行

php - MySQL获取一组中每x分钟的列的平均值和总和

c# - 更新实体错误 : A second operation started on this context before a previous operation completed

c# - 将 Kusto 客户端响应转换为对象列表会返回空对象

c# - 命名空间和文件夹之间的关系

c# - 直接更改 DataGridView 中的值

sql - 带参数的 AS400 SQL 查询

c# - CodePlex 对表达式树序列化库的看法?

entity-framework - 更新 Entity Framework 对象