我正在运行一个相当密集的数据查询(因此长超时),但想知道如何正确排序DataTable
。
我的代码是这样开始的:
SqlDataAdapter da = new SqlDataAdapter();
SqlCommand command = new SqlCommand(sql, conn);
command.CommandTimeout = 36000;
da.SelectCommand = command;
DataTable dt = new DataTable();
da.Fill(dt);
DataView dv = new DataView(dt);
// Sorting
dv.Sort = "theId DESC";
int i = 0;
while (dt.Rows.Count > 0 && i < 5)
{
DataRow row = dt.Rows[i];
string theId = row["theId"].ToString();
i++;
}
theId
有大约2,000条记录,这些记录按数字顺序从1到2,000。
ORDER BY
的警告是由于异常:
ERROR: Exception occurred
查询处理器无法生成查询计划,因为需要一个工作表,并且它的最小行大小超过了允许的最大8060字节,等等
我也不能即时创建#TempTable
,因为最大列大小为1,024。
以某种方式编写查询的原因是由于我给出的系统和网络的限制,不能调整,也不能在本地运行。
我如何得到排序的DataTable
工作,因为这是需要传递到下一个函数,这也是我的控制之外,因为它是一个api调用到另一个系统?
你不能真正排序一个DataTable
。您可以通过DataView
进行排序,正如您所做的那样,但这只对视图排序,而不是对表排序。如果随后通过Rows
集合访问数据,则不会看到排序。你必须通过DataView
访问数据。
实际上不需要显式地创建DataView
。每个DataTable
在其DefaultView
属性中已经有一个DataView
。当您在WinForms中绑定DataTable
时,这就是未播放数据的来源。这就是如何在DataGridView
中或通过BindingSource
对数据进行排序。
当您使用Rows
集合时,您将获得DataRow
对象。当您使用DefaultView
时,您将获得DataRowView
对象。他们在许多方面很相似,但也有一些不同之处。如果您只需要数据,则可以使用列名进行索引并获取值,因此它们在这方面的工作方式相同。如果您通过DefaultView
访问数据,但由于某种原因需要DataRow
,则可以通过DataRowView
的Row
属性访问它。试试下面的代码,看看它是如何工作的:
var table = new DataTable();
table.Columns.Add("Name", typeof(string));
table.Rows.Add("Peter");
table.Rows.Add("Paul");
table.Rows.Add("Mary");
Console.WriteLine("Rows, unsorted");
foreach (DataRow row in table.Rows)
{
Console.WriteLine(row["Name"]);
}
Console.WriteLine("DefaultView, unsorted");
foreach (DataRowView rowView in table.DefaultView)
{
Console.WriteLine(rowView["Name"]);
}
table.DefaultView.Sort = "Name";
Console.WriteLine("Rows, sorted");
foreach (DataRow row in table.Rows)
{
Console.WriteLine(row["Name"]);
}
Console.WriteLine("DefaultView, sorted");
foreach (DataRowView rowView in table.DefaultView)
{
Console.WriteLine(rowView["Name"]);
}
Console.WriteLine("DefaultView to DataRow, sorted");
foreach (DataRowView rowView in table.DefaultView)
{
Console.WriteLine(rowView.Row.Field<string>("Name"));
}
您可以看到,Rows
集合中的数据在排序前后是相同的,而DefaultView
则按照指定的顺序显示数据。最后一个循环展示了如何从DataRowViews
访问DataRows
,然后在DataRowViews
不能使用的地方使用它们,例如在LINQ to DataSet方法中。
注意,如果你真的需要对DataTable
本身进行排序,那么你可以在DataView
上调用ToTable
来生成一个新的DataTable
。新表将包含基于DataView
的Sort
和RowFilter
属性的数据,如果您愿意,也可以省略一些列。您还可以指定只包含不同的记录。