0

继续我之前描述我的模式的问题(为方便起见,在此重复):

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.

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

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();
}
4

1 回答 1

0

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

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

于 2013-05-15T21:59:26.667 回答