DataView.Sort 和 DataTable.OrderBy().AsDataView() 之间的区别?

发布于 2024-09-26 16:31:49 字数 847 浏览 4 评论 0原文

我有一个 DataGridView ,它绑定到一个 DataTable ,其中包含我需要排序的自定义类型列。此自定义类型 (MyCustomType) 实现了 IComparable,这就是我希望排序的工作方式。

我尝试了两种方法来创建一个 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 是否可能使用我的 IComparable 实现以及支持 LINQ 的 DataView ?为什么会这样呢?

此外,有人知道不支持 LINQ 的 DataView 和支持 LINQ 的 DataView 的相对性能吗?看起来,如果性能没有受到巨大影响,就没有理由再使用不支持 LINQ 的版本。

I have a DataGridView which is bound to a DataTable that contains a column of custom types that I need to sort by. This custom type (MyCustomType) implements IComparable<MyCustomType> which is how I wanted the sorting to work.

I tried 2 methods to create a DataView which I would use as the grid's data source:

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

This did not really work properly - it "almost" worked, but sometimes my rows would not be sorted correctly.

Second method:

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

This seems to be doing what I want. My question is, what's the difference between these two methods? Is it possible that DataView.Sort is not using my IComparable<T> implementation, and the LINQ-enabled DataView is? Why would that be the case?

Furthermore, does anyone know about the relative performance of non-LINQ-enabled and LINQ-enabled DataViews? It seems like if there isn't a huge performance hit, there's no longer any reason to use the non-LINQ-enabled version.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

左耳近心 2024-10-03 16:31:49

我正在为其他想知道 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

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

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)},
};

如果有人看到此内容并可以建议一种映射数据列的方法 ->不依赖 Func<> 的字段 lambda返回动态类型,任何建议都将受到欢迎。

I'm posting comparisons for anyone else wondering how Linq-DataView performs vs non-Linq-DataView, especially since the results surprised me. For this test, at least, old DataView's an order of magnitude faster than Linq-enabled 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

Linq-DataView vs non-Linq-DataView for untyped dtbl (seconds)

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()

OrderBy for v2 (with in-line comment for 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)},
};

If anyone ever sees this and can suggest a way of mapping datacolumns -> Field lambdas without relying on a Func<> returning a dynamic type, any suggestion would be most welcome.

何以心动 2024-10-03 16:31:49

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

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

抱歉,我没有说清楚。

When you call .Sort on the DataView, it sorts this particular instance of the object. Your second method actually creates a brand new object and assigns to the dv variable. This can be a critical difference.

EDIT: Not your second method specifically, since you're not assigning, then re-assigning. But if you had an existing DataView, then re-assigned it using the OrderBy method, then you'd have the scenario I suggested.

Sorry, I wasn't as clear as I should have been.

骑趴 2024-10-03 16:31:49

DataView.Sort 是内置于 DataView 类中的方法,而 .OrderBy 是扩展。

DataView.Sort is a method that is built into the DataView class whereas .OrderBy is an Extension.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文