加速 Entity Framework 4.2 POCO

5
我正在使用Entity Framework 4.2,遇到了一个相当严重的性能问题。我采用了POCO方法,继承自DbContext,并且以下是一个解释问题的小样例:
我有一个包含两个表A和B的数据库:

A

  • AId(int - 非空 - identity - 主键)
  • Name(nvarchar(50)- 非空)

B

  • BId(int - 非空 - identity - 主键)
  • SomeValue(int - 非空)
  • AId(int - 非空 - 外键连接到表A中的AId)
A表中只有一行数据(1,“Test”),而B表中有6000行数据(SomeValue只是从0到5999的数字),所有这些行都通过外键列引用A行。
我从数据库创建edmx并关闭代码生成,然后创建以下类:
public class DatabaseContext : DbContext
{
    public DatabaseContext(string name) : base(name)
    {
        Configuration.AutoDetectChangesEnabled = false;
        As = Set<A>();
        Bs = Set<B>();
    }

    public DbSet<A> As { get; private set; }
    public DbSet<B> Bs { get; private set; }
}

public class A
{
    public virtual int AId { get; set; }
    public virtual string Name { get; set; }
    public virtual ICollection<B> Bs { get; private set; }

    public void AddB(B b)
    {
        if (b == null)
        {
            throw new ArgumentNullException("b");
        }

        if (Bs == null)
        {
            Bs = new List<B>();
        }

        if (!Bs.Contains(b))
        {
            Bs.Add(b);
        }

        b.A = this;
    }
}

public class B
{
    public virtual int BId { get; set; }
    public virtual A A { get; set; }
    public virtual int SomeValue { get; set; }
}

现在我只需要做以下事情:
var ctx = new DatabaseContext("ScalabilityTestEntities");
var a = ctx.As.FirstOrDefault();
a.Bs.Add(new B { SomeValue = 987 });

在我的四核、4GB RAM的64位Windows 7机器上,将新的B添加到最后一行大约需要6秒钟时间,同时数据库也运行在本地。

真正糟糕的是,它似乎呈指数级恶化,因为如果你将B的行数加倍,它需要近20秒钟的时间!

我非常希望能得到任何加快这一过程的提示。非常感谢!

2个回答

4
导航属性的世界可能会让人非常痛苦。我们基本上不得不逐步淘汰它们的使用,因为它们会在背后引起许多性能问题(特别是当您涉及到连接和分离实体时,但这是另一个故事)。
具体发生的情况是,当您访问a.Bs时,它会加载该A的所有B。
在这种特定情况下,如果您实际上不需要完整的B列表,只想添加一个新的B,那么最好只需创建一个B并将其AId设置为a的ID。

3
在这种情况下,您应该禁用延迟加载:
var ctx = new DatabaseContext("ScalabilityTestEntities");
ctx.Configuration.LazyLoadingEnabled = false;
var a = ctx.As.FirstOrDefault();
a.Bs = new List<B>();
a.Bs.Add(new B { SomeValue = 987 });

您默认启用了懒加载(这会在访问集合时加载所有6000个B),因为导航集合被声明为virtual。如果您永远不需要或不想使用懒加载,应将virtual关键字全部删除或在上下文构造函数中禁用懒加载。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接