DataTable.Select() 返回空数组是因为默认只查 DataRowState.Unchanged 行,Deleted 或未 AcceptChanges 的 Added 行不参与筛选;筛选字符串中字符串值须加单引号,null 要写成 IS NULL,LIKE 仅支持 % 和 _。

DataTable.Select() 筛选时为什么返回空数组?
因为 Select() 默认只在当前行状态(DataRowState.Unchanged)中查找,已标记为 Deleted 或刚 Added 但未 AcceptChanges() 的行不会被查到。调试时用 DataTable.GetChanges() 看实际变更状态。
筛选字符串要加单引号,数值不用:table.Select("Name = '张三' AND Age > 25")table.Select("Status = 1")
常见错误写法(会抛异常或无结果):
-
"Name = 张三"—— 缺少单引号,当成列名解析 -
"Age >= null"——null要写成IS NULL -
"Name LIKE '%李%'"——LIKE只支持%和_,不支持正则
用 DataView.Sort 排序比 DataTable.DefaultView.Sort 更安全
DataView 是独立视图,排序不会影响原 DataTable 的行物理顺序;而直接操作 DataTable.DefaultView.Sort 虽然也有效,但多个地方共用默认视图时容易互相干扰。
正确做法是显式创建新视图:
var view = new DataView(table) { Sort = "CreateTime DESC, Name ASC" };
foreach (DataRowView row in view) { /* 处理排序后数据 */ }注意点:
- 排序字段名大小写敏感,且必须存在于
DataTable.Columns中 - 不能对表达式列(如
table.Columns.Add("FullName", typeof(string), "FirstName + ' ' + LastName"))直接排序,需先Compute()或用 LINQ - 含
null的列排序时,null默认排最前(升序)或最后(降序),不可配置
合并两个 DataTable:Merge() 不等于 AppendRows
DataTable.Merge() 是按主键(PrimaryKey)或指定列匹配更新/插入/保留,不是简单拼接。没设主键?那所有行都当新增处理,可能造成重复。
合并前务必检查:
- 目标表是否已设置
PrimaryKey(如table.PrimaryKey = new[] { table.Columns["Id"] };) - 源表结构是否兼容:列名、类型、允许空值需一致,否则抛
InvalidCastException - 调用时传
true表示保留目标表更改(PreserveChanges = true),但会禁用自动更新逻辑,慎用
若只是追加行,更推荐手动遍历:
foreach (DataRow r in source.Rows) {
table.ImportRow(r); // 自动适配列映射,比 NewRow()+逐字段赋值更稳
}用 LINQ to DataSet 替代复杂筛选排序时的坑
引用 System.Data.DataSetExtensions 后,AsEnumerable() 让 DataTable 支持 LINQ,但要注意性能和语义差异:
-
table.AsEnumerable().Where(r => r.FieldCount > 0)——FieldCount是行属性,不是列数,别误用 -
r.Field<int>("Age")</int>比(int?)r["Age"]更安全,空值不抛异常 - 排序用
OrderBy(r => r.Field<string>("Name"))</string>,但无法像DataView那样复用索引,大数据量时明显变慢 - 不能在 LINQ 查询中修改原行(如
r.SetField("X", 1)),会破坏延迟执行逻辑,要先.ToList()再改
真实项目里,简单条件用 Select(),带计算或跨表逻辑才切到 LINQ;合并场景优先考虑 ImportRow 或 Load(),别迷信 Merge()。


















