Difference between DataView.Sort and DataTable.OrderBy().AsDataView()?
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 re开发者_C百科lative performance of non-LINQ-enabled and LINQ-enabled DataView
s? It seems like if there isn't a huge performance hit, there's no longer any reason to use the non-LINQ-enabled version.
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.
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.
DataView.Sort is a method that is built into the DataView class whereas .OrderBy is an Extension.
精彩评论