实体框架在循环中创建对象时速度减慢



我有一个员工类,如下

[Table("employee")]
[DataContract(Name = "employee"]
public class Employee
{
[Key]
[DataMember(Name = "Id", IsRequired = true)]
public int Id { get; set; }
[DataMember(Name = "Name", IsRequired = true)]
public string Name { get; set; }
[DataMember(Name = "empCode", IsRequired = true)]
public int Code{ get; set; }
}

在另一个类中,我使用foreach循环为上表创建记录。newEmps是返回特定数据的不同查询的结果集。

var empList= new List<Employee>();
foreach (var employee in newEmps)
{
var emp= new Employee();
emp.ID = employee.ID;
emp.Name = employee.Name;
emp.Code = employee.code;
empList.Add(emp);
}

newEmps的计数约为6500,而在创建6500 Employee对象时,Entity速度减慢,每次执行foreach循环需要超过10分钟,这比300秒的超时时间还要长。

在某些场景中,这是有效的,但在某些情况下,它会引发以下异常。-系统数据实体果心EntityCommandExecutionException:执行命令定义时出错。有关详细信息,请参阅内部异常。--->系统数据SqlClient。SqlException:执行超时已过期。操作完成前经过的超时时间或服务器没有响应。--->系统组件模型。Win32Exception:等待操作超时。

这种异常在大多数情况下都会发生,但有时也会发生。

尝试使用BulkInsert来解析System.Data.SqlClient.SqlException

var empList= new List<Employee>();
foreach (var employee in newEmps)
{
var emp= new Employee();
emp.ID = employee.ID;
emp.Name = employee.Name;
emp.Code = employee.code;
empList.Add(emp);
}
yourContext.BulkInsert(empList);  //★BulkInsert

更新#1

关于缓慢的前臂循环。

如果您大致知道范围,请尝试使用List(Int32(

例如:

var empList= new List<Employee>(10000);

我认为跟踪newEmps实体的问题。在EF中,查询的实体由上下文自动跟踪,允许您修改它们(如有必要(,然后将更改与上下文一起保存。SaveChanges((操作。

禁用跟踪可能会加快应用程序的速度。如果您只使用newEmps进行读取,您可以尝试使用AsNoTracking((查询newEmps,如下所示。

var newEmps = await context.DbSet.AsNoTracking().FirstOrDefaultAsync();

或者,您可以通过更改上下文跟踪行为来更改foreach循环中的跟踪行为。

context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
var empList= new List<Employee>();
foreach (var employee in newEmps)
{
var emp= new Employee();
emp.ID = employee.ID;
emp.Name = employee.Name;
emp.Code = employee.code;
empList.Add(emp);
}
context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.TrackAll;

这里有两篇关于EF跟踪性能的有用文章。

使用AsNoTracking加快实体框架性能

第3部分。使用AsNoTracking((。但明智的

最新更新