如何在相关的SQL表上通过EF快速批量插入?

时间:2017-11-06 03:53:25

标签: sql-server performance entity-framework bulkinsert

我有一个包含2个表的数据库:

Apartment: ID, Name, Address
Tenant: ID, Name, Phone, ApartmentID

每间公寓可以有一个以上的租户,但每个租户只能在一个公寓内。

还有一个API可以返回当前的公寓列表,以及该公寓中作为JSON列表的租户列表:

Apartments : [
    { 
        Name: 'Sherwood', 
        Address: '21 Woody Lane' ,  
        Tenants : [
            { Name: 'Robin', Phone: '111-1111' },
            { Name: 'Hood', Phone: '222-2222' } 
        ]
    }, 

    ...


]

我需要将API结果解析为2个相关对象,即公寓和租户,并将它们插入到数据库中。 API返回了大量条目,大约500,000条。为了加快速度,我采取了以下方面的想法:Fastest Way of Inserting in Entity Framework

但是,该帖子中有一个概念我无法在我的解决方案中实现,即推迟SaveChanges()。这就是我目前的代码(概念):

Foreach apartment
    Insert apartment into DB
    SaveChanges()
    Get ID of inserted apartment
    Foreach tenant in apartment
         Insert tenant into DB, into apartment ID

上述结构的原因是,当插入租户行时,我需要该租户所居住的公寓ID,因此我需要在公寓之前插入(并保存更改以获取ID)插入租户。

这导致SaveChanges()被多次调用并损害性能。如何优化上述解决方案?

2 个答案:

答案 0 :(得分:1)

您可以指定导航属性 - EF将在保存时处理它,如下所示:

Foreach apartment
  dbContext.Appartments.Add(apartment);
  foreach tenant
    tenant.Appartment = apartment;
    dbContext.Tenants.Add(tenant);
  endforeach tenant
endforeach apartment

SaveChanges();

答案 1 :(得分:0)

实体框架中没有Bulk Insert。您必须使用第三方库来执行此类操作。

默认情况下,Entity Framework将为每个要保存的实体进行数据库往返。因此,您的方案中需要超过500,000次数据库往返, INSANELY 缓慢。

免责声明:我是Entity Framework Extensions

的所有者

此库不是免费的,但允许您执行所有批量操作,包括BulkInsert并自动返回Id's。您还可以使用IncludeGraph选项插入相关实体:

  • 批量保存更改
  • 批量插入
  • 批量删除
  • 批量更新
  • 批量合并

实施例

// Easy to use
context.BulkSaveChanges();

// Easy to customize
context.BulkSaveChanges(bulk => bulk.BatchSize = 100);

// Perform Bulk Operations
context.BulkDelete(customers);
context.BulkInsert(customers);
context.BulkUpdate(customers);

// Customize Bulk Operations
context.BulkInsert(customers, options => {
   options => options.IncludeGraph = true;
});
context.BulkMerge(customers, options => {
   options.ColumnPrimaryKeyExpression = 
        customer => customer.Code;
});