【发布时间】:2014-04-03 08:13:37
【问题描述】:
在实体上填充过滤的子 EntityCollection 时,EntityFramework 似乎非常慢 -
我们正在运行 RIA/WCF Web 应用程序,该应用程序使用以 C# 编写的数据库优先实体框架和 Silverlight 客户端。我们收集了大约 70,000 个“Eval”实体和类似数量的“InCo”实体。每个 Eval 都有一个包含最多 2 个 InCo 实体的子集合。这种关系是一对多的,因此一个 Eval 可以有多个 InCo,但一个 InCo 绑定到一个 Eval。从数据库加载实体集合后,我像这样循环遍历 Eval -
foreach(Eval eval in Evals)
if (eval.InCos.Count > 0)
// Do something
这需要很长时间(分钟)。单步执行代码我发现在 Eval 实体上有一个生成的函数 FilterInCos 来确定 InCo 是否与它有关联(在生成的 .Web.g.cs 文件中)并将其传递给Eval 的 InCos EntityCollection 的构造函数,并在第一次引用其属性之一时调用以填充该集合
private bool FilterInCos(InCo entity)
{
return (entity.EvalID == this.EvalID);
}
据我所见,每个 Eval 的 InCos 集合中的每个 InCo 都会调用 FilterInCos() 函数 - 即 70,000 个 Eval 中的每一个都调用了 70,000 次,导致大约 50 亿次迭代循环遍历 Eval 并查询 InCos收集到每一个。由于 Eval:InCo 数据库关系为 1:*,因此应该可以遍历 InCo 对象,检索具有匹配 EvalID 的 Eval 并将 InCo 添加到该 Eval 的 InCos 集合中 - 70,000 次迭代。但是,正如我所见,似乎没有办法绕过生成的逻辑。我们也不能只将 EntityCollection 分配给 Eval 的 InCos 属性,因为它是只读的。
这是来自 EF edmx 文件的相关数据库关系 -
<Association Name="FK_InCo_Eval">
<End Role="Eval" Type="AspireEntityModel.Store.Eval" Multiplicity="1">
<OnDelete Action="Cascade" />
</End>
<End Role="InCo" Type="AspireEntityModel.Store.InCo" Multiplicity="*" />
<ReferentialConstraint>
<Principal Role="Eval">
<PropertyRef Name="EvalID" />
</Principal>
<Dependent Role="InCo">
<PropertyRef Name="EvalID" />
</Dependent>
</ReferentialConstraint>
</Association>
这是带有生成构造函数的 Eval 客户端实体(来自生成的 .Web.g.cs)上的 InCos 属性
/// <summary>
/// Gets the collection of associated <see cref="InCo"/> entity instances.
/// </summary>
[Association("Eval_InCo", "EvalID", "EvalID")]
[XmlIgnore()]
public EntityCollection<InCo> InCos
{
get
{
if ((this._InCos == null))
{
this._InCos = new EntityCollection<InCo>(this, "InCos", this.FilterInCos, this.AttachInCos, this.DetachInCos);
}
return this._InCos;
}
}
是否有人在数据库优先的 EF 应用程序上发现了类似的行为并可以提出解决方法?
【问题讨论】:
标签: c# entity-framework ria