这不是一个真正的问题,但更多的是担心我会很感激你的一些意见。
Winforms C#.net3.5 [sp1] Visual Studio 2008使用Linq2Sql(更具体地说是PLINQO ...这真是太棒了!)。我有一个结果集返回+/- 19000行数据(每行约80字节数据)并选择将数据检索方法推送到后台并相应地更新UI。这很好。
但是,当我的Ling数据检索方法使用不同的返回类型时,我注意到了一些性能差异。我知道每个人都建议返回List<T>
或IEnumarable<T>
,并将DataGridView的数据源设置为该数据源,但遗憾的是它不支持对象进行原生排序。经过一番挖掘后,我在MSDN here找到了SortableBindingList<T>
。我应用了它,并且网格花了一秒钟来填充自己 - 但是当我点击一列来对它进行排序时,实现排序花了一点多时间。
然后我决定使用DataTable路由,但发现ToDataTable方法已被删除,但经过多次挖掘后找到了在MSDN article上实现它的方法。应用它之后,我发现检索大约花了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查询道歉!
答案 0 :(得分:1)
这是我对你的问题的看法(走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条记录,但专门的比较器在70毫秒内完成相同的工作。
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;
}
}
最后一点:发布的大部分代码都是从SO或微软等其他来源复制/启发的,所以信用不是我的。我唯一的贡献是虚拟化比较器,但我相信一点点谷歌搜索会表现出更好的,早期的解决方案基于相同的想法。