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

C# 实体框架在循环中创建对象时速度减慢,c#,entity-framework,C#,Entity Framework,我有一个employee类,如下所示 [表格(“员工”)] [数据合同(Name=“employee”] 公营雇员 { [关键] [数据成员(Name=“Id”,IsRequired=true)] 公共int Id{get;set;} [数据成员(Name=“Name”,IsRequired=true)] 公共字符串名称{get;set;} [数据成员(Name=“empCode”,IsRequired=true)] 公共整数代码{get;set;} } 在另一个类中,我使用foreach循环

我有一个employee类,如下所示

[表格(“员工”)]
[数据合同(Name=“employee”]
公营雇员
{
[关键]
[数据成员(Name=“Id”,IsRequired=true)]
公共int Id{get;set;}
[数据成员(Name=“Name”,IsRequired=true)]
公共字符串名称{get;set;}
[数据成员(Name=“empCode”,IsRequired=true)]
公共整数代码{get;set;}
}
在另一个类中,我使用foreach循环为上面的表创建记录

var empList=new List();
foreach(新EMPS中的var员工)
{
var emp=新员工();
emp.ID=employee.ID;
emp.Name=employee.Name;
emp.Code=employee.Code;
雇主添加(emp);
}
新EMP的计数约为6500,而创建6500个Employee对象时,实体速度会减慢,并且此foreach循环执行需要10分钟以上,这比超时300秒还要长

在某些情况下,这是可行的,但在某些情况下,它会引发以下异常。-System.Data.Entity.Core.EntityCommandExecutionException:在执行命令定义时出错。有关详细信息,请参阅内部异常。-->System.Data.SqlClient.SqlException:执行超时已过期。超时时间在执行完成之前已过操作或服务器没有响应。-->System.ComponentModel.Win32异常:等待操作超时


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

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

var empList=new List();
foreach(新EMPS中的var员工)
{
var emp=新员工();
emp.ID=employee.ID;
emp.Name=employee.Name;
emp.Code=employee.Code;
雇主添加(emp);
}
yourContext.BulkInsert(雇员列表)//★隔板

更新#1

关于慢速foreach循环

如果您大致了解范围,请尝试使用

例如:

var empList=新列表(10000);

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

var empList=new List();
foreach(新EMPS中的var员工)
{
var emp=新员工();
emp.ID=employee.ID;
emp.Name=employee.Name;
emp.Code=employee.Code;
雇主添加(emp);
}
yourContext.BulkInsert(雇员列表)//★隔板

更新#1

关于慢速foreach循环

如果您大致了解范围,请尝试使用

例如:

var empList=新列表(10000);

我认为跟踪新EMPS实体存在问题。在EF中,查询的实体由上下文自动跟踪,允许您修改它们(如有必要),然后使用context.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;
context.ChangeTracker.QueryTrackingBehavior=QueryTrackingBehavior.NoTracking;
var empList=新列表();
foreach(新EMPS中的var员工)
{
var emp=新员工();
emp.ID=employee.ID;
emp.Name=employee.Name;
emp.Code=employee.Code;
雇主添加(emp);
}
context.ChangeTracker.QueryTrackingBehavior=QueryTrackingBehavior.TrackAll;
这里有两篇关于EF跟踪性能的有用文章


我认为跟踪新EMPS实体存在问题。在EF中,查询的实体由上下文自动跟踪,允许您修改它们(如有必要),然后使用context.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;
context.ChangeTracker.QueryTrackingBehavior=QueryTrackingBehavior.NoTracking;
var empList=新列表();
foreach(新EMPS中的var员工)
{
var emp=新员工();
emp.ID=employee.ID;
emp.Name=employee.Name;
emp.Code=employee.Code;
雇主添加(emp);
}
context.ChangeTracker.QueryTrackingBehavior=QueryTrackingBehavior.TrackAll;
这里有两篇关于EF跟踪性能的有用文章


尝试批量处理,例如100…即在循环中每100次提交一次保存。我正在使用SqlBulkCopy执行批量插入。当显示的代码确实存在此问题时,问题不在创建,但newEmps的newEmpsQuery中的查询返回正确的数据,它会在创建6500个Employee对象时变慢。for each循环需要非常长的时间ng time.是新员工的创建?还是保存部分?因为只创建新的
foreach
循环不会点击
sqlexception
。所以我认为异常是在大量的savingtry批处理中,比如说在循环中每100次提交一次保存。我正在使用SqlBulkCopy执行批量插入。实际上,显示的代码没有他的问题然后问题不是创建,但是newEmps的newEmpsQuery中的查询返回正确的数据,它在创建6500个Employee对象时会减慢速度。for-each循环需要很长时间。是创建新的Employee?还是保存部分?因为只创建新的
foreach
循环不会点击
sqlexception
。所以我认为在savingise中是个例外。问题是foreach循环,创建6500名员工需要很多时间。因此,您有两个问题:1.foreach循环缓慢(如您所说)。原因仍然未知。2.System.Data.SqlClient.SqlException:执行超时已过期。我在上面的回答中介绍了一种可能的解决方案。问题在于foreach循环,创建6500名员工需要大量时间。因此