性能关于返回类型LINQ查询与自动分拣兼容
-
21-09-2019 - |
题
这是不是一个真正的问题,但更多的,我将不胜感激,请输入一些担心的。
使用LINQ2SQL的Winforms C#.NET3.5 [SP1]的Visual Studio 2008(更具体地 PLINQO ...这太棒了顺便说一句!)。我有一个结果返回+/- 19000行的数据(约每行数据的80bytes)和选择推数据检索方法的背景,并相应地更新用户界面。这工作得很好。
不过,我用不同的返回类型为我的灵数据检索方法时已经注意到了一些性能上的差异。我知道每个人都建议返回List<T>
或IEnumarable<T>
,并在DataGridView的数据源设置为,但遗憾的是它不支持的对象本身的排序。经过一番周围挖我发现 MSDN的SortableBindingList<T>
这里。我申请了,和网格下了第二填充本身 - 但是当我在一列点击排序,它花了一点在一秒钟左右,以实现排序
然后我决定去DataTable的路线,但发现该ToDataTable方法已被删除,但经过挖掘发现了一种方法来实现它在这的 MSDN文章。应用它之后,我发现了检索2秒左右填充网格,但此后排序(上19000行!)是瞬间完成!当然,我坚持这种方法。
此外请,我已经禁用了任何在并网编辑/添加/删除的想法。网格是纯粹用于显示数据。任何其他CRUD操作由对话框形式根据当前选择的行(隐藏主键列)提供。
下面是我用这两种方法的代码:
<强> 1)SortableBindingList 强>
//declare private member
private SortableBindingList<PdtAllocation> listAlloc = null;
private void RefreshData() {
bcsDataContext ctx = new bcsDataContext();
try {
listAlloc = new SortableBindingList<PdtAllocation>(ctx.PdtAllocation.ToList());
}
catch (Exception) {
throw;
}
finally {
ctx.Dispose();
}
dataGridView1.DataSource = listAlloc;
}
<强> 2)CopyToDatatable 强>
//declare private member
private DataTable dt = null;
private void RefreshData() {
dt = new DataTable();
bcsDataContext ctx = new bcsDataContext();
try {
ctx.PdtAllocation.CopyToDataTable(dt, LoadOption.PreserveChanges);
}
catch (Exception) {
throw;
}
finally {
ctx.Dispose();
}
dataGridView1.DataSource = dt;
}
现在我知道这可能看起来像一个“的问-和回答的”情况,但我会很感激你的输入,以及同去的CopyToDataTable()
航线任何已知的问题。
感谢ü....并为looong查询的歉意!
解决方案
这是我拿上你的问题(打算在SortableBindingList
路线)。
你使用排序算法基于一个通用的,反映?我这样做是在第一和性能是非常糟糕的。最后,我想出了以下解决方案:提供默认的排序SortableBindingList<T>
还留下打开的可能性以实现在派生类专业排序
下面是一些代码。
在SortableBindingList<T>.ApplySortCore()
:
protected override void ApplySortCore(PropertyDescriptor prop, ListSortDirection direction)
{
// Check if the sorted property implements IComparable
...
List<T> itemsList = (List<T>)this.Items;
Comparison<T> comparer = GetComparer(prop);
itemsList.Sort(comparer);
if (direction == ListSortDirection.Descending)
{
itemsList.Reverse();
}
...
// Set sort state (is sorted, sort property, sort dir)
}
通用SortableBindingList<T>
提供了一个基本的,基于反射分拣机:
protected virtual Comparison<T> GetComparer(PropertyDescriptor prop)
{
return new Comparison<T>(delegate(T x, T y)
{
if (prop.GetValue(x) != null)
return ((IComparable)prop.GetValue(x)).CompareTo(prop.GetValue(y));
else if (prop.GetValue(y) != null)
return -1 * ((IComparable)prop.GetValue(y)).CompareTo(prop.GetValue(x));
else
return 0;
});
}
可以看到,GetComparer()
是虚拟的,所以可以在从SortableBindingList<T>
派生的类重写它,以便提供一个多更快比较器,调整以所述属性的类型实际上排序。例如,虽然一般比较器在4秒排序(通过String
属性)10000个记录,专门比较器也做了同样的工作在70ms的。
class CustomerList : SortableBindingList<Customer>
{
protected override Comparison<Customer> GetComparer(PropertyDescriptor prop)
{
Comparison<Customer> comparer = null;
switch (prop.Name)
{
case "FirstName":
comparer = new Comparison<Customer>(delegate(Customer x, Customer y)
{
string xx = (null == x) ? null : x.FirstName;
string yy = (null == y) ? null : y.FirstName;
return String.Compare(xx, yy);
});
break;
...
}
return comparer;
}
}
最后请注意:多贴被复制/来自其他来源,像这样或Microsoft启发的代码,所以信贷的不是我。我唯一的贡献是虚拟化的比较器,但我敢肯定一点谷歌搜索将基于同样的想法,表面更好,更早的解决方案。