C# DataView.Sort与DataTable.OrderBy()和AsDataView()之间的差异?
我有一个DataGridView,它绑定到一个DataTable,其中包含一列我需要排序的自定义类型。这个自定义类型MyCustomType实现了IComparable,这就是我希望排序工作的方式 我尝试了两种方法来创建一个DataView,并将其用作网格的数据源:C# DataView.Sort与DataTable.OrderBy()和AsDataView()之间的差异?,c#,linq,dataview,C#,Linq,Dataview,我有一个DataGridView,它绑定到一个DataTable,其中包含一列我需要排序的自定义类型。这个自定义类型MyCustomType实现了IComparable,这就是我希望排序工作的方式 我尝试了两种方法来创建一个DataView,并将其用作网格的数据源: MyDataTable dt = new MyDataTable(); DataView dv = new DataView(dt); dv.Sort = "MyCustomField"; 这并没有真正正常工作-它几乎正常工作,但
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和启用LINQ的数据视图的相对性能?似乎如果性能没有受到很大的影响,就没有理由再使用非LINQ启用的版本了。DataView.Sort是DataView类中内置的一个方法,而.OrderBy是一个扩展。在DataView上调用.Sort时,它会对对象的这个特定实例进行排序。您的第二个方法实际上创建了一个全新的对象并分配给dv变量。这可能是一个关键的区别 编辑:不是您的第二种方法,因为您没有分配,然后重新分配。但是,如果您有一个现有的DataView,然后使用OrderBy方法重新分配它,那么您就有了我建议的场景
很抱歉,我没有说得那么清楚。我正在为其他想知道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数据视图与非Linq数据视图
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,那么任何建议都是非常受欢迎的。当然,这不一定是您想要的区别,但这是一个重要的区别,我想我实际上可能是在代码dv=dv.Whatever.AsDataView中这样做的。似乎这两种方法在框架中使用了非常不同的代码。我发现你可以用AsDataView返回的任何东西做一些有趣的事情,但它很快就开始看起来像未记录的巫毒。我很清楚这一有记录的简单区别。我不明白这怎么解释我看到的行为。