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