DevExpress eXpressApp 框架 (XAF) 和 eXpress 持久对象 (XPO):如何加快关联的加载时间?
-
09-06-2019 - |
题
我在访问具有大量记录的关联属性时遇到速度问题。
我有一个 XAF 应用程序,其父类名为 MyParent
.
共有 230 条记录 MyParent
.
MyParent
有一个名为的子类 MyChild
.
有 49,000 条记录 MyChild
.
我在之间定义了一个关联 MyParent
和 MyChild
以标准方式:
在 MyChild
:
// MyChild (many) and MyParent (one)
[Association("MyChild-MyParent")]
public MyParent MyParent;
并且在 MyParent
:
[Association("MyChild-MyParent", typeof(MyChild))]
public XPCollection<MyCHild> MyCHildren
{
get { return GetCollection<MyCHild>("MyCHildren"); }
}
有一个具体的 MyParent
记录被叫 MyParent1
.
为了 MyParent1
, 有 630 个 MyChild
记录。
我有一个名为 DetailView 的类 MyUI
.
用户在一个下拉列表中选择一项 MyUI
DetailView,我的代码必须填充另一个下拉列表 MyChild
对象。
用户选择 MyParent1
在第一个下拉列表中。
我创建了一个属性 MyUI
返回集合 MyChild
第一个下拉列表中所选值的对象。
这是该属性的代码:
[NonPersistent]
public XPCollection<MyChild> DisplayedValues
{
get
{
Session theSession;
MyParent theParentValue;
XPCollection<MyCHild> theChildren;
theParentValue = this.DropDownOne;
// get the parent value
if theValue == null)
{
// if none
return null;
// return null
}
theChildren = theParentValue.MyChildren;
// get the child values for the parent
return theChildren;
// return it
}
我标记了 DisplayedValues
财产为 NonPersistent
因为只有 DetailVIew 的 UI 才需要它。我不认为持久化它会加快第一次创建集合的速度,并且在使用它填充下拉列表后,我不需要它,所以我不想花时间存储它。
问题是调用需要45秒 theParentValue = this.DropDownOne
.
眼镜:
- 维斯塔商务
- 8 GB 内存
- 2.33GHz E6550 处理器
- SQL Server Express 2005
对于用户来说,等待 DetailView 中众多下拉菜单之一的时间太长。
我花时间勾勒出业务案例,因为我有两个问题:
如何使关联值加载得更快?
是否有另一种(简单)方法来对运行速度更快的下拉菜单和 DetailView 进行编程?
是的,你可以说 630 的项目太多,无法在下拉列表中显示,但这段代码花费了很长时间,我怀疑速度与 49,000 成正比,而不是与 630 成正比。下拉列表中的 100 个项目对于我的应用程序来说并不算太多。
我的应用程序中需要相当多的此类下拉菜单,因此强制用户为每个下拉菜单输入更复杂的过滤条件是不合适的。用户需要选择一个值并查看相关值。
如果查找大量记录很慢,我会理解,但查找几百条记录应该不会花那么长时间。
解决方案
首先,您对这个操作应该花费这么长时间的怀疑是正确的,读操作上的 XPO 应该只增加 30 - 70% 的开销,并且对于这么少量的数据,我们应该谈论毫秒而不是秒。
DevExpress 论坛中提供了一些通用的性能技巧,主要围绕对象缓存、惰性加载与深度加载等,但我认为在您的情况下问题是其他的,不幸的是很难从您的问题中猜测发生了什么,仅可以说,它不太可能是 XPO 的问题,更可能是其他问题,我倾向于查看您的会话创建(这也会创建您的对象缓存)和 SQL 连接代码(IDataStore 的东西),连接是如果主机无法完全解析,并且您没有池化/重用连接,则通常会很慢,此问题可能会加剧。
其他提示
我不确定你为什么要这样做。如果您创建了这样的关联:
public class A : XPObject
{
[Association("a<b", typeof(b))]
public XPCollection<b> bs { get { GetCollection("bs"); } }
}
public class B : XPObject
{
[Association("a<b") Persistent("Aid")]
public A a { get; set; }
}
然后当您想要填充下拉列表时(例如 LookupEdit 控件)
A myA = GetSomeParticularA();
lupAsBs.Properties.DataSource = myA.Bs;
lupAsBs.Properties.DisplayMember = "WhateverPropertyName";
您不必加载 A 的子级,XPO 将在需要时加载它们,并且根本不需要会话管理。
感谢你的回答。正如您所建议的,我创建了一个单独的解决方案并且能够获得良好的性能。
我的 SQL 连接正常,并且可以与应用程序中的其他功能配合使用。
鉴于我正在使用 XAF 并且没有做任何额外/花哨的事情,我的会话不是由 XAF 管理的吗?
我使用的会话是从 DetailView 中读取的。
我不确定你的情况,只是想分享一些我使用 XAF 的经验。
第一次单击下拉(查找列表)控件(在详细视图中)时,将有两个查询发送到数据库以填充列表。在我的测试中,有时整个对象都会加载到源集合中,而不仅仅是 ID 和 Name 属性,因为我们认为这取决于您的对象,您可能希望对列表使用较轻的对象。您还可以打开列表的服务器模式,这样每次只加载 128 个对象。