我使用类似循环(简化,无错误检查)的在线数据填充数据库:
foreach (var catalog in catalogs)
{
var result = Items(catalog, state, context);
while (result != null)
{
result.ForEach(r => context.DbContext.Items.Add(r));
context.DbContext.SaveChanges();
result = Items(catalog, state, context);
}
}
代码需要一些时间才能从服务器获得XML响应,并使用响应流上的XElement.Load将其解码为XElement。它被解码为一个项目列表,其中最多包含50个项目-这是我在每个循环过程中从服务器请求的。由于SaveChanges调用,该块立即被保存到表中。。
8/10的循环时间要么花在向DbContext添加项上,要么花在SaveChanges调用中,要么同时花在这两者上。与远程服务器的通信以及将响应XML解码为实体列表是2/10。
如何在保留EF的同时提高将数据存储到数据库中的效率?
我知道我可以从XML大容量加载数据库,但这将迫使我计算出需要编写的SQL语句,因为上面的SaveChanges调用会更新几个相关的表,因此我开始失去使用EF的优势。
简而言之:使用纯EF无法加快插入过程,因为EF在批量/批处理数据方面的性能非常差。你有两个问题:
- 将实体添加到上下文中会产生一些成本,并且这种成本随着上下文中已经存在的每个实体而增加。为了避免这种情况,您可以尝试在每次调用
Add
之后调用SavaChanges
,甚至尝试在每次批处理甚至每次调用Add
时使用新的上下文 - EF为您想要插入、更新或删除的每个记录提供了一个单独的数据库往返,因此您调用
SaveChanges
的频率通常无关紧要。只有当使用直接SQL并创建一个SqlCommand
同时执行所有插入时,才有可能避免这种情况
如果您想提高性能,请使用直接SQL。