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

标签 c# entity-framework-4

我们的代码中有一个通用的更新方法,它执行一个

foreach (var entity in entityList)
{
    Context.GetIDbSet<T>().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<MyClass> MyClassSet { get; set; }
}

...和这个测试程序...

using (var context = new MyContext())
{
    var list = new List<MyClass>();
    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<MyClass>().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<MyClass>().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 秒

因此,如果没有更改跟踪,属性的数量就不再那么重要了。


结论

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

编辑

以上测试时间为Debug模式。但 Release 模式没有太大区别(例如:测试 1 = 28.7 秒,测试 5 = 0.9 秒)。

关于c# - 是什么导致 .Attach() 在 EF4 中变慢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5917478/

相关文章:

c# - 分发需要 Microsoft.Office.Interop.Excel 的应用程序

c# - 升级到 EF 6.1.1 使 [NotMapped] 的效果消失

.net - EF Code First 映射内部关联

entity-framework-4 - EF4 外键与唯一键的关系无法识别

c# - 如何在维护关系的同时最好地扩展 Entity Framework 生成的 POCO 对象

c# - 带有 String.Format 奇怪编译器错误的扩展方法

c# - 检查可选包是否存在

c# - 使用反射等效于 default(T)

c# - 如何将数据库结果限制为只有一个?

c# - self 跟踪实体 SaveChanges() 在多对多关系中添加实体时出现异常