是什么导致.Attach()在EF4中变慢?

我们的代码中有一个通用的更新方法

foreach (var entity in entityList) { Context.GetIDbSet().Attach(entity); Context.SetState(entity, EntityState.Modified); } 

我通过传入一个实体的枚举并按每个实体调用一次来测试它。

我发现的是1000个实体的枚举大约需要47秒才能运行。 这是预期的行为吗? 或者代码片段有问题吗?

分析显示Attach()方法比SetState()方法慢。

我运行的测试是在具有50个属性的实体上,如果有任何影响则没有关系。

我可以证实这种缓慢的行为,我也找到了主要原因。 我用以下型号做了一点测试……

 public class MyClass { public int Id { get; set; } public string P1 { get; set; } // ... properties P2 to P49, all of type string public string P50 { get; set; } } public class MyContext : DbContext { public DbSet MyClassSet { get; set; } } 

……而且这个测试程序……

 using (var context = new MyContext()) { var list = new List(); for (int i = 0; i < 1000; i++) { var m = new MyClass() { Id = i+1, P1 = "Some text ....................................", // ... initialize P2 to P49, all with the same text P50 = "Some text ...................................." } list.Add(m); } Stopwatch watch = new Stopwatch(); watch.Start(); foreach (var entity in list) { context.Set().Attach(entity); context.Entry(entity).State = System.Data.EntityState.Modified; } watch.Stop(); long time = watch.ElapsedMilliseconds; } 

测试1

正是上面的代码:

– > 时间= 29,2秒


测试2

注释掉这条线……

 //context.Entry(entity).State = System.Data.EntityState.Modified; 

– > 时间= 15,3秒


测试3

注释掉这条线……

 //context.Set().Attach(entity); 

– > 时间= 57,3秒

这个结果很奇怪,因为我预计调用Attach是没有必要的,因为无论如何都要改变状态。


测试4

删除属性P6到P50(因此我们在实体中只有5个字符串),原始代码:

– > 时间= 3,4秒

所以,是的,很明显,物业的数量非常重要。


测试5

在循环之前添加以下行(再次使用所有50个属性建立模型):

 context.Configuration.AutoDetectChangesEnabled = false; 

– > 时间= 1,4秒


测试6

AutoDetectChangesEnabled = false但只有5个属性:

– > 时间= 1,3秒

所以,没有变化跟踪,属性的数量就不再那么重要了。


结论

到目前为止,大部分时间似乎都花费在通过更改跟踪机制获取附加对象属性的快照。 如果您不需要,请停用代码段的更改跟踪。 (我想在你的代码中你真的不需要更改跟踪,因为通过将entitit的状态设置为Modified你基本上将所有属性标记为已更改。所以所有列都会在更新语句中发送到数据库。)

编辑

上面的测试时间是在调试模式下。 但释放模式没有太大的区别(例如:测试1 = 28,7秒,测试5 = 0,9秒)。