gpt4 book ai didi

c# - 需要使用 Entity Framework 加快将大对象图写入数据库的速度

转载 作者:行者123 更新时间:2023-11-30 15:14:45 27 4
gpt4 key购买 nike

我在当前项目中使用 EntityFramework Core。在这个项目中,我有一个接受大型 (4,000K) 文本文件的 API 端点。端点读取并解析文件并将数据转换为对象图。

然后我需要将整个图表写入 SQL 数据库。解析文本文件后,我在这个对象图中找到了大约 20,000 个对象。

图通常有一个事务。该交易有大约 5000 个订阅者,每个订阅者平均有 4 个利益。每个 Dates 集合将有 1 个或 2 个 DateRanges。拒绝通常是空的。

我的对象图基本上是这样的:

public class Transaction {
public int Id {get; set;}
... // Other properties
public ICollection<Subscriber> Subscribers {get; private set;}
public ICollection<TranRejection> Rejections {get; private set;}
}

public class Subscriber {
public int Id {get; set;}
public int TransactionId {get; set;} //Foreign Key
... // Other properties
public ICollection<Benefit> Benefits {get; private set;}
public ICollection<SubscriberRejection> Rejections {get; private set;}
public ICollection<SubscriberDateRange> Dates {get; private set;}
}

public class Benefit {
public int Id {get; set;}
public int SubscriberId {get; set;} //Foreign Key
... // Other properties
public ICollection<BenefitRejection> Rejections {get; private set;}
public ICollection<BenefitDateRange> Dates {get; private set;}
}

//This abstract class w/ empty subclasses is done to take advantage of TPH
//so that all dates get stored in a single table
public abstract class DateRange {
public int Id {get; set;}
public int ParentId {get; set;}
public string DateCode {get; set;}
public DateTime BeginRange {get; set;}
public DateTime? EndRange {get; set;}
}

public class BenefitDateRange : DateRange {}
public class SubscriberDateRange : DateRange {}

//Rejection class is handled very similar to DateRange

我的 EF 映射看起来像这样。 (只包括重要的部分以帮助查看关系)。

builder.Entity<DateRange>().ToTable("dateranges")
.HasDiscriminator<string>("rangetype")
.HasValue<BenefitDateRange>("benefit")
.HasValue<SubscriberDateRange>("subscriber");
builder.Entity<DateRange>().HasKey(r => r.Id);

builder.Entity<Transaction>().HasMany(t => t.Subscribers).WithOne()
.HasForeignKey(s => s.TransactionId);

builder.Entity<Subscriber>().HasMany(s => s.Benefits).WithOne()
.HasForeignKey(b => b.SubscriberId);

builder.Entity<Subscriber>().HasMany(s => s.Dates).WithOne()
.HasForeignKey(d => d.ParentId);

//Similar mappings for Benefit.Dates
//Rejections are using TPH just like DateRanges

我尝试通过单独保存片段来保存到数据库——即保存没有订阅者的交易,然后保存每个订阅者,等等。这至少需要 30 分钟。

然后我切换到像这样一次保存整个图表:

_dbContext.AddRange(transactions);
_dbContext.SaveChanges();

这大约需要 5 分钟。但是,这是 API 调用的一部分,我想加快速度。有没有更快的方法将整个图形保存到数据库中?我不应该为此使用 EF 吗?

最佳答案

我们遇到了类似的问题,但少了一个级别。最适合我们的解决方案是使用 BulkExtensions 并将每个级别包装在一个 try-catch block 中,如果保存错误则回滚所有更改。

https://github.com/borisdj/EFCore.BulkExtensions

没有外部库的 native 选项是关闭 DBContext 上的 AutoDetectChangesEnabled 和 ValidateOnSaveEnabled。但它仍然比使用 BuilExtensions 慢一点。

context.Configuration.AutoDetectChangesEnabled = false;
context.Configuration.ValidateOnSaveEnabled = false;

我们的用例是始终插入新行而不是更新现有行。因此,我无法评价 BulkExtensions 的 InsertOrUpdate 方法的性能。但是,值得一试。

关于c# - 需要使用 Entity Framework 加快将大对象图写入数据库的速度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53871289/

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