gpt4 book ai didi

c# - Entity Framework 批量插入虚幻缓慢

转载 作者:行者123 更新时间:2023-11-30 14:50:33 24 4
gpt4 key购买 nike

我正在使用 EF 6。我尝试插入大约 200.000 个实体,同时在每 100 个实体后保存对数据库的更改。

问题是花了 11 个小时才保存了 50.000 个实体,而且仍然落后。我正在使用 WebJobs 运行它,并且作业发布在与主网站相同的 azure web 应用程序上。问题是因为 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<DeliveryRecord>().Insert(deliveryRecord);

_unit.SaveChangesPartially(rowCounter, 100);
}

_unit.SaveChanges();
}

helper

public static class UnitOfWorkHelper
{
/// <summary>
/// Helper method triggers SaveChanges() after amount of rows provided through "amount" parameter in method
/// </summary>
/// <param name="unit">UnitOfWork object</param>
/// <param name="count">Current amount of rows</param>
/// <param name="saveCount">Amount when to save changes to database</param>
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 个专业)允许批量插入

// Example from Entity Framework Extensions Library
using (var ctx = new EntitiesContext())
{
ctx.BulkInsert(list);
}

您可以阅读以下文章来了解每个库的优点和缺点:Entity Framework - Bulk Insert Library Reviews & Comparisons

Entity Framework Extensions是迄今为止提供最大灵 active 的库(批量插入、更新、删除、合并和批量保存更改并支持所有功能),但它是 PRO 版本。如果您正在寻找免费版本,我建议使用EntityFramework.BulkInsert,但是,它不再受支持,并且不支持所有关联和继承。

免责声明:我是该项目的所有者 Entity Framework Extensions

编辑:回答评论问题

I am saving each 100 records, not each record

无论您向单元上下文添加一个实体还是 100 个实体, Entity Framework 都会一一保存它们(每条记录一条插入语句)。只需将 SQL Profiler 与 SQL Server 数据库结合使用,您就会明白我的意思。

编辑:回答评论问题

great jonathan. is there any way to implement this with ef6 generic uow?

答案取决于您选择使用哪个库。

如果您使用我的库,您可以创建 BulkSaveChanges 方法或在 UnitOfWork 中将所有“_context.SaveChanges()”更改为“_context.BulkSaveChanges()”

public void SaveLeadsForBuyer(ISenderModel model)
{
// ... code ...
// _unit.SaveChanges();
_unit.BulkSaveChanges();
}

如果您想要最佳性能并从我的库或免费库实现批量插入,我可能会添加一个名为 BulkInsert 的方法或扩展方法(如果您无法更改存储库类)

public class Repository<TEntity> : IRepository<TEntity> where TEntity : class
{
// ... code ...

public virtual void BulkInsert(List<TEntity> list)
{
_context.BulkInsert(list);
}
}

请记住,BulkInsert 直接插入实体而无需调用“SaveChanges”,它不使用上下文/更改跟踪器来获得最佳性能。

关于c# - Entity Framework 批量插入虚幻缓慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36245732/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com