1

我有一个DataGridView绑定到DataTable包含我需要排序的自定义类型列的 a。这个自定义类型 ( MyCustomType) 实现IComparable<MyCustomType>了我希望排序工作的方式。

我尝试了 2 种方法来创建一个DataView用作网格数据源的方法:

MyDataTable dt = new MyDataTable();
DataView dv = new DataView(dt);
dv.Sort = "MyCustomField";

这并没有真正正常工作 - 它“几乎”工作,但有时我的行无法正确排序。

第二种方法:

MyDataTable dt = new MyDataTable();
DataView dv = dt.OrderBy(row => row.MyCustomField).AsDataView();

这似乎正在做我想要的。我的问题是,这两种方法有什么区别?是否有可能DataView.Sort没有使用我的实现,并且启用了 LINQ 的?为什么会这样?IComparable<T>DataView

此外,有人知道非启用 LINQ 和启用 LINQ 的相对性能DataView吗?似乎如果没有巨大的性能影响,则不再有任何理由使用不支持 LINQ 的版本。

4

3 回答 3

1

我正在为其他想知道 Linq-DataView 与非 Linq-DataView 性能如何的人进行比较,特别是因为结果让我感到惊讶。对于这个测试,至少,旧的 DataView 比启用 Linq 的 DataView 快一个数量级。

v1: Linq-DataView, on-the-fly sort string -> OrderBy/ThenBy via Field<dynamic>()
v2: Linq-DataView, on-the-fly via mapped Field<type>()
v3: Linq-DataView, hard-coded OrderBy/ThenBy
v4: non-Linq DataView w/sort string

无类型 dtbl 的 Linq-DataView 与非 Linq-DataView(秒)

03.411  v1 = dtbl.AsEnumerable().OrderBy("T30y, Dat desc").AsDataView();
02.561  v2 = dtbl.AsEnumerable().OrderBy(dtbl, "T30y, Dat desc").AsDataView();
01.573  v3 = dtbl.AsEnumerable().OrderBy(y=>y.Field<decimal>("T30y"))
                                .ThenByDescending(y=>y.Field<DateTime>("Dat")).AsDataView();
00.214  v4 = new DataView(dtbl, "", "T30y, Dat desc", DataViewRowState.CurrentRows);

02.403  v1: 100,000 iterations of Find()
01.708  v2: 100,000 iterations of Find()
01.173  v3: 100,000 iterations of Find()
00.261  v4: 100,000 iterations of Find()

v2 的 OrderBy(带有 v1 的内嵌注释)

static public EnumerableRowCollection<DataRow>
    OrderBy( this EnumerableRowCollection<DataRow> ys, DataTable dtbl, string sort )
{
    OrderedEnumerableRowCollection<DataRow> oys = null;
    foreach ( string s in (sort ?? "").Split(new []{", "}, StringSplitOptions.None) )
    {
        int n = s.IndexOf(" desc");
        string x = n!=-1 ? s.Substring(0, n) : s;
        Type typ = dtbl.Columns[x].DataType;
        Func<DataRow,dynamic> vfn = y=>yget[typ](y,x); // v1: vfn = y.Field<dynamic>(x)

        if ( oys==null )
             oys = s.Contains(" desc") ? ys.OrderByDescending(vfn) : ys.OrderBy(vfn);
        else oys = s.Contains(" desc") ? oys.ThenByDescending(vfn) : oys.ThenBy(vfn);
    }
    return oys ?? ys;
}

static Dictionary<Type,Func<DataRow,string,dynamic>>
    yget = new Dictionary<Type,Func<DataRow,string,dynamic>>
{
    {typeof(bool),     (y,x)=>y.Field<bool>(x)},
    {typeof(short),    (y,x)=>y.Field<short>(x)},
    {typeof(int),      (y,x)=>y.Field<int>(x)},
    {typeof(string),   (y,x)=>y.Field<string>(x)},
    {typeof(decimal),  (y,x)=>y.Field<decimal>(x)},
    {typeof(float),    (y,x)=>y.Field<float>(x)},
    {typeof(double),   (y,x)=>y.Field<double>(x)},
    {typeof(DateTime), (y,x)=>y.Field<DateTime>(x)},
    {typeof(TimeSpan), (y,x)=>y.Field<TimeSpan>(x)},
};

如果有人看到这一点并且可以建议一种映射 datacolumns -> Field lambdas 而不依赖于 Func<> 返回动态类型的方法,那么任何建议都将受到欢迎。

于 2014-12-23T16:04:29.797 回答
0

当您调用.SortDataView 时,它会对对象的这个特定实例进行排序。您的第二种方法实际上创建了一个全新的对象并分配给dv变量。这可能是一个关键的区别。

编辑:不是你的第二种方法,因为你没有分配,然后重新分配。但是,如果您有一个现有的 DataView,然后使用 OrderBy 方法重新分配它,那么您就会得到我建议的场景。

对不起,我没有像我应该说的那么清楚。

于 2011-03-03T20:25:02.757 回答
-1

DataView.Sort 是一种内置在 DataView 类中的方法,而 .OrderBy 是一个扩展。

于 2011-03-03T20:21:30.980 回答