我有一个包含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()被多次调用并损害性能。如何优化上述解决方案?
答案 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;
});