2012-03-08 124 views
1

我们的应用存在巨大的性能问题,我们从不同的系统收集数据并将其保存在我们的数据库中,以便稍后生成一些报告。使用EF4.2批量插入

我们使用实体框架4.2和DbSets,有没有这样做批量插入,然后Add方法有关DbSet每个实体的更好的办法?因为有与添加逻辑

oneThousandCustomers.Foreach(c => context.Customers.Add(c)); //This will take a minute 
context.SaveChanges(); //This takes under a second 

巨大的性能问题,我想add方法是引擎盖下做大量的查找等之类的东西,但我只是想批量插入这些数据。可能吗?

回答

1

好吧,所以这里的交易是,当你将项目添加到集合时,EF在场景下做了大量的工作。

在性能方面真正的大的事情是,它调用DetectChanges()自动上列举了整个对象图中的每个add命令。

这意味着,如果你有这正在由目前的EF上下文跟踪大量的项目,这将导致一些非常严重的性能问题。

下面有一些提示,以提高性能,作为比较,我可以插入1000个没有FK的相当简单的实体EF在1/2第二下。

  • 确保您使用的是新的EF上下文实例为您的查询, 这将确保您的图形变化很小,因此增加会 相当快。为的DbContext

代码

  • 打开自动变化检测来关闭自动检测更改

    context.Configuration.AutoDetectChangesEnabled = false; 
    

    当禁用AutoDetectChanges你需要小心一点,因为它意味着大部分EF的automagic被关闭,所以你可能会感到奇怪,特别是如果你正在使用导航属性或正在更新现有的实体。要解决这些问题,请在调用SaveChanges之前调用DetectChanges。这会降低性能,并且不需要简单的添加操作,因此在您的示例中,如果没有此操作,您可能会离开。

    这个这个MSDN文章谈到,(注意:即使它的EF 5的相同4)http://msdn.microsoft.com/en-us/library/gg696177%28v=vs.103%29.aspx

  • +0

    我们使用CQRS框架,并且每个请求注入上下文,更改上下文的行为有点危险,因为不能保证命令逻辑的其他部分在更改上下文行为后不会使用上下文。 – Anders 2012-03-08 10:00:03

    +0

    如果您想要EF的好处,性能是危险的并且涉及妥协,那么您需要处理性能问题或手动管理环境以优化性能。如果你不想这样做,你也想要性能,那么不要使用EF。但是,我对CQRS,消息传递和批量导入以及EF(对于查询和写入)都做了完全相同的事情,并且它工作正常。 – 2012-03-08 11:16:31

    +0

    我们选择这一个,因为它很容易改变我们现有的代码。所有的单元测试和场景测试都是绿色的,所以它看起来像在工作!谢谢! – Anders 2012-03-09 08:40:21

    0

    您可以使用LinqEntityDataReader对实体集合,这将提高性能进入此链接描述您的应用程序执行SqlBulkCopy的。

    +0

    将检查出来,谢谢! – Anders 2012-03-08 10:03:54