我有一个员工类,如下
[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((。但明智的