ame*_*els 3 c# entity-framework azure azure-webjobs
我正在使用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<DeliveryRecord>().Insert(deliveryRecord);
_unit.SaveChangesPartially(rowCounter, 100);
}
_unit.SaveChanges();
}
Run Code Online (Sandbox Code Playgroud)
帮手
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();
}
}
}
Run Code Online (Sandbox Code Playgroud)
它很慢,因为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);
}
Run Code Online (Sandbox Code Playgroud)
您可以阅读以下文章来了解每个库的PROS和CONS:实体框架 - 批量插入库评论和比较
Entity Framework Extensions是提供最大灵活性的库(Bulk Insert,Update,Delete,Merge和BulkSaveChanges并支持所有内容),但它是PRO版本.如果您正在寻找免费版本,我建议使用EntityFramework.BulkInsert,但是,它不再受支持,并且不支持所有关联和继承.
免责声明:我是项目实体框架扩展的所有者
编辑:回答评论问题
我保存每100条记录,而不是每条记录
如果向单元上下文添加一个实体或100个实体并不重要,实体框架会逐个保存它们(每个记录都有一个插入语句).只需将SQL事件探查器与SQL Server数据库一起使用,您就会明白我的意思.
编辑:回答评论问题
伟大的乔纳森.有没有办法用ef6通用uow实现这个?
答案取决于您选择使用哪个库.
如果您使用我的库,您可以创建BulkSaveChanges方法或在您的UnitOfWork中更改所有"_context.SaveChanges()"by"_context.BulkSaveChanges()"
public void SaveLeadsForBuyer(ISenderModel model)
{
// ... code ...
// _unit.SaveChanges();
_unit.BulkSaveChanges();
}
Run Code Online (Sandbox Code Playgroud)
如果你想从我的库或免费库中获得最佳性能和实现批量插入,我可能会添加一个名为BulkInsert的方法或扩展方法(如果你不能更改存储库类)
public class Repository<TEntity> : IRepository<TEntity> where TEntity : class
{
// ... code ...
public virtual void BulkInsert(List<TEntity> list)
{
_context.BulkInsert(list);
}
}
Run Code Online (Sandbox Code Playgroud)
请记住,BulkInsert直接插入实体而不必调用"SaveChanges",它不使用上下文/更改跟踪器来获得最佳性能.
| 归档时间: |
|
| 查看次数: |
1282 次 |
| 最近记录: |