entity framework批量插入虚幻慢
我正在使用EF 6.我试图插入大约200.000个实体,同时在每100个实体后保存对数据库的更改。
问题是需要11个小时来保存50.000个实体,它仍然落后。 我正在使用WebJobs运行它,并且作业在与主网站相同的azure webapp上发布。 问题是因为和WebJob没有足够的资源,或者在100个实体之后保存,还是方法?
方法
public void SaveLeadsForBuyer(ISenderModel model) { var rowCounter = 0; foreach (var deliveryRecord in model.Customers.Select(customerModel => new DeliveryRecord() { BuyerId = model.Buyer.Id, AspNetUserId = customerModel.Id, DeliveryType = model.Buyer.DeliveryType, CreatedOn = DateTime.UtcNow })) { ++rowCounter; _unit.Repository().Insert(deliveryRecord); _unit.SaveChangesPartially(rowCounter, 100); } _unit.SaveChanges(); }
帮手
public static class UnitOfWorkHelper { /// /// Helper method triggers SaveChanges() after amount of rows provided through "amount" parameter in method /// /// UnitOfWork object /// Current amount of rows /// Amount when to save changes to database public static void SaveChangesPartially(this IUnitOfWorkAsync unit, int count, int saveCount) { if (count % saveCount == 0) { unit.SaveChanges(); } } }
它很慢,因为Entity Framework为每条记录执行数据库往返。 因此,如果您节省了200,000个实体,那么将执行200,000次数据库往返 ,这对于保存多个实体来说是最佳的。
对于这种情况,您需要自己实现或使用支持BulkInsert的库(通常在引擎盖下执行SqlBulkCopy)
有3个主库(2个免费,1个PRO)允许批量插入
// Example from Entity Framework Extensions Library using (var ctx = new EntitiesContext()) { ctx.BulkInsert(list); }
您可以阅读以下文章来了解每个库的PROS和CONS: entity framework – 批量插入库评论和比较
Entity Framework Extensions是提供最大灵活性的库(Bulk Insert,Update,Delete,Merge和BulkSaveChanges并支持所有内容),但它是PRO版本。 如果您正在寻找免费版本,我建议使用EntityFramework.BulkInsert,但是,它不再受支持,并且不支持所有关联和inheritance。
免责声明 :我是项目entity framework扩展的所有者
编辑:回答评论问题
我保存每100条记录,而不是每条记录
如果向单元上下文添加一个实体或100个实体并不重要,entity framework会逐个保存它们(每个记录都有一个插入语句)。 只需将SQL事件探查器与SQL Server数据库一起使用,您就会明白我的意思。
编辑:回答评论问题
伟大的乔纳森。 有没有办法用ef6通用uow实现这个?
答案取决于您选择使用哪个库。
如果您使用我的库,您可以创建BulkSaveChanges方法或在您的UnitOfWork中更改所有“_context.SaveChanges()”by“_context.BulkSaveChanges()”
public void SaveLeadsForBuyer(ISenderModel model) { // ... code ... // _unit.SaveChanges(); _unit.BulkSaveChanges(); }
如果你想从我的库或免费库中获得最佳性能和实现批量插入,我可能会添加名为BulkInsert的方法或扩展方法(如果你不能更改存储库类)
public class Repository : IRepository where TEntity : class { // ... code ... public virtual void BulkInsert(List list) { _context.BulkInsert(list); } }
请记住,BulkInsert直接插入实体而不必调用“SaveChanges”,它不使用上下文/更改跟踪器来获得最佳性能。
- 通过代码调用时获取Powershell命令的输出
- 使用AzureSearch SDK与30-40 ISearchIndexClients的静态字典的含义
- 如何在没有登录的情况下使用window azure media server的文件路径阻止播放video?
- 为什么我的Azure WebJobs“settings.job”文件被忽略?
- 身份validation在调试时成功但在Azure App Service上失败
- 活动Azure Sql连接超出了连接池限制
- CreateDocumentCollectionIfNotExistsAsync并不总是有效
- 连续Azure WebJob何时停止NoAutomaticTrigger类型作业的通知
- 如何跟踪异步文件上传到azure存储的进度