如何改进实体框架批量插入

时间:2014-07-22 08:47:20

标签: 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排队到List中,然后将整个列表添加到DB Context。

或许我正在看这一切都错了,我应该完全避免使用EntityFramework来获得更高性能的插件?目前它是我应用程序中的瓶颈,如果我查看系统资源,SQL似乎甚至不会让人眼前一亮。

所以我的问题:

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

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

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

[编辑]

进一步解释这个场景。我有一个循环在concurrentQueue上的线程,该队列从这个队列中取出项目。然而,由于db插入物是瓶颈的事实。队列中经常有数千个条目,所以如果还有异步或并行方式,我可以使用多个线程来进行插入。

1 个答案:

答案 0 :(得分:4)

对于涉及大量插入的场景,我倾向于单独使用&#34;缓冲区&#34; (在内存中,或redis列表,或其他),然后作为批处理作业(可能每分钟,或每隔几分钟)读取列表并使用SqlBulkCopy尽可能有效地将数据投入数据库。为了解决这个问题,我使用了fastmemberObjectReader.Create方法,该方法将List<T>(或任何IEnumerable<T>)公开为IDataReader,可以将其输入SqlBulkCopy,将T的属性公开为数据读取器中的逻辑列。然后,您需要做的只是填充缓冲区中的List<T>

但是,请注意,您需要考虑&#34;出现问题&#34;场景;即如果插入失败了一半,你如何处理缓冲区中的数据?这里的一个选项是将SqlBulkCopy放入 staging 表(相同的架构,但不是&#34; live&#34;表),然后使用常规INSERT当你知道它在数据库中时,一步复制数据 - 这使得恢复变得更简单。