实体框架性能 - 如何让它快速运行?

时间:2013-04-18 01:42:37

标签: c# entity-framework entity

我有一个包含子对象列表的对象,基本上它是一个有多个部门的机构。可以根据部门上的布尔属性禁用或启用部门。当有一个或多个禁用的部门时,我想触发该机构的财产为假。我的部分机构课程中有以下代码:

public bool AllSet
{
    get
    {
        return !(Departments.Where(i => i.Active == false && i.IsDeleted == false).Count() > 0);
    }
}

这样可行,但是当我启用它时,我的页面的性能显示机构列表减慢了爬行和内存使用量的峰值,显然我在这里做了一些根本性的错误,有没有人有任何替代方法来做到这一点?

工作解决方案

    var institutions = from x in ent.Institutions let hasDepartments = 
!x.Departments.Any(d => d.Active == false && d.IsDeleted == false) select new { 
                FullTitle = x.Title + " - " + x.Address.Line1 + ", " + x.Address.City + ", " + x.Address.State, Department = x, AllSet = hasDepartments, Guid = x.Guid
            };
            instList.DataSource = institutions;

2 个答案:

答案 0 :(得分:1)

你可以使用:

public bool AllSet
{
    get
    {
        return !(Departments.Count(i => i.Active == false && i.IsDeleted == false) > 0);
    }
}

有提高EF效果的提示,请查看link。 (对于那些使用EF的人来说,这值得一读)

答案 1 :(得分:1)

您应该通过使用以下查询找到边际性能优势。然而,主要的问题是Linq是无形的。根据定义,它在运行时生成SQL查询,为此,会生成大量元数据。你会发现.net 4.5在这方面的开销比.net 4低。

如果第一个查询的成本似乎很高,那么也可能是由于视图创建过程造成的。您可以查看预编译的视图。但最终如果您需要速度,请查看其他地方。甚至可能是内联SQL。

public bool AllSet
{
    get
    {
        return !(Departments.Any(i => i.Active == false && i.IsDeleted == false));
    }
}

编辑:我刚刚意识到你的真实问题。看起来AllSet是类Institution的一个方法,你在紧密的循环中调用它。由于延迟加载,我认为它“正常工作”。

这非常糟糕,因为您将要进行数据库调用的每个循环,这将是IO /延迟限制,因此非常慢。此外,不是仅从数据库加载bool,而是按需加载每个关联的Department,然后在.net上本地运行.Count()(因此占用大量内存)。

如果他们有活跃的部门,请尝试预取每个机构。

var institutions = from x in context.Institutions
                   where {blah}
                   let hasDepartments = x.Departments.Any(d => d.Active == false 
                                   && i.IsDeleted == false)
                   select new { Department = x, AllSet = hasDepartments};
foreach(var institution in institutions)
{
    //DO STUFF
}

总的来说,真正的WTF是你依赖EF Lazy Loading。