加载对象的大多数相关实体非常慢

时间:2013-05-14 18:49:19

标签: entity-framework

Continuing from my earlier question where I described my schema(为方便起见,这里重复):

Parties ( PartyId, ClientId, AddressId, DateTime )
Tents ( PartyId, TentDetails... )
Clowns ( PartyId, AddressId, ClownDetails... )
SecurityAgentAssignment ( PartyId, AgentId, fromTime, untilTime )
Addresses ( AddressId, Street, City, State )

....还有大约10个类似设计的其他表格:与Parties的多对一关系。

我的ASP.NET MVC Web应用程序有一个“摘要”页面,显示有关聚会的所有详细信息。我正在使用EF1.0,所以我必须自己加载。这是我正在使用的逻辑:

Party dbParty = GetParty(partyId);

dbParty.Tents.EnsureLoaded();
dbParty.Clowns.EnsureLoaded();
foreach(Clown clown in dbParty.Clowns) clown.Address.EnsureLoaded();
dbParty.Security.EnsureLoaded();
foreach(SecurityAgentAssignment assignment in dbParty.Security) assignment.Agent.EnsureLoaded();
// and the 10 other relationships too

上面的代码大约需要3秒钟才能运行。鉴于这不是急切加载,而是延迟加载,当然它应该只关闭15个简单的SELECT查询并完成?

我没有安装SQL Server Profiler,而且在使用.Load而不是IQueryable时,我不知道如何获取SQL。

我使用这些扩展方法作为助手:

private static readonly R.FieldInfo    _entityReferenceContext = typeof(RelatedEnd).GetField("_context", R.BindingFlags.Instance | R.BindingFlags.NonPublic );
private static readonly R.PropertyInfo _relatedEndOwner        = typeof(RelatedEnd).GetProperty("Owner", R.BindingFlags.Instance | R.BindingFlags.NonPublic );

private static Boolean IsAttached(this RelatedEnd relatedEnd) {

    Object context =  _entityReferenceContext.GetValue( relatedEnd );
    return context != null;
}

public static TEntity EnsureLoaded<TEntity>(this EntityReference<TEntity> eref) where TEntity : class, IEntityWithRelationships {

    // EntityReference<TEntity> derives from RelatedEnd.
    RelatedEnd erefAsRelatedEnd = (RelatedEnd)eref;

    erefAsRelatedEnd.EnsureLoaded();

    return eref.Value;
}

public static void EnsureLoaded(this RelatedEnd end) {

    IEntityWithRelationships owner       = (IEntityWithRelationships)_relatedEndOwner.GetValue( end, null );
    EntityObject             ownerEntity = owner as EntityObject;

    if( ownerEntity != null ) {

        if( ownerEntity.EntityState == EntityState.Added || ownerEntity.EntityState == EntityState.Detached ) return; // calling .Load on a Added object causes an exception.
    }

    if( end.IsAttached() && !end.IsLoaded ) end.Load();
}

1 个答案:

答案 0 :(得分:0)

这个问题没有实际意义 - 我通过VPN连接连接到我的数据库服务器。我认为没关系,因为我的计算机和数据库服务器之间的ping时间只有50毫秒左右,但我忘记了SQL Server的繁琐程度。考虑到它一次触发大约60个查询,60 * 50ms == 3000ms

是有意义的

当我在与服务器相同的LAN上重试我的应用程序时(ping时间<1ms),整个加载操作在30ms内执行,无需进一步优化。问题解决了。