如何正确获取DataRowView的索引?相等判断失效原因与解决
DataRowView索引获取失败的原因、场景及解决方法
为什么==比较会返回false?
DataRowView是引用类型,但DataView的索引器(DataView[i])每次被访问时,都会返回一个全新的DataRowView实例——即便这些实例对应的是DataTable中的同一行数据,它们的引用地址也不相同。而==运算符对引用类型的默认行为是比较引用地址,所以会出现“明明行存在但比较结果为false”的情况。
常见触发场景
- 缓存过某个DataRowView实例,之后直接通过
DataView[i]获取实例并和缓存的实例做引用比较 - 数据绑定场景(如WinForms的DataGridView、WPF的DataGrid):控件返回的DataRowView实例,和直接从绑定的DataView中通过索引获取的实例不是同一个引用
- DataView执行过排序、筛选、刷新(
DataView.Refresh())操作后,重新获取的DataRowView实例和之前的引用不一致
正确获取索引的方法
方法1:比较底层DataRow(最通用)
同一行数据对应的DataRow引用是唯一的,通过比较DataRowView.Row的引用,可以准确匹配到对应行:
public static int GetIndex(this DataRowView rowView) { DataView view = rowView.DataView; for (int i = 0; i < view.Count; i++) { if (view[i].Row == rowView.Row) return i; } return -1; }
方法2:利用主键查找(效率更高)
如果DataTable定义了主键,使用DataView.Find()方法可以直接定位索引,无需遍历整个DataView,效率大幅提升:
public static int GetIndexByPrimaryKey(this DataRowView rowView) { DataView view = rowView.DataView; DataTable table = view.Table; // 检查是否有主键定义 if (table.PrimaryKey == null || table.PrimaryKey.Length == 0) return -1; // 提取当前行的主键值 object[] keyValues = new object[table.PrimaryKey.Length]; for (int i = 0; i < table.PrimaryKey.Length; i++) { keyValues[i] = rowView[table.PrimaryKey[i].ColumnName]; } return view.Find(keyValues); }
方法3:比较所有列值(无主键时备选)
如果没有主键,可以通过比较行的所有列值来匹配,但要注意处理null值和数据类型的兼容性:
public static int GetIndexByRowValues(this DataRowView rowView) { DataView view = rowView.DataView; DataTable table = view.Table; for (int i = 0; i < view.Count; i++) { DataRowView currentView = view[i]; bool isMatch = true; foreach (DataColumn col in table.Columns) { object val1 = rowView[col.ColumnName]; object val2 = currentView[col.ColumnName]; // 处理null值的情况 if (val1 == DBNull.Value && val2 == DBNull.Value) continue; if (val1 == null || val2 == null || !val1.Equals(val2)) { isMatch = false; break; } } if (isMatch) return i; } return -1; }
内容的提问来源于stack exchange,提问作者fikewek832
相关产品推荐
相关产品推荐

