使用过滤版本的 DataTable 的最佳方式是什么?

What is the best way to use a filtered version of a DataTable?

我有一个包含 4 个 DataTableDataSet,比如 dt1dt2dt3dt4。我也有 3 个这样的 DataRelation

|Parent|Child|
|  d1  |  d2 |
|  d2  |  d3 |
|  d2  |  d4 |

我的 MasterClass 将此 DataSet 传递给多个 class,每个 class 需要使用 DataSet 执行不同的操作。但是,在通过 DataSet 之前,MasterClass 需要对 dt1 执行过滤,因为每个 class 都需要与 dt1 的过滤版本一起使用。请注意,我无法更新 dt1,因为我需要对同一个 DataTable 执行不同的过滤器。在下图中,我尝试可视化结构:

我的问题是:将过滤后的 dt1 传递给 Class A..B 的最佳方法是什么?

我想到的第一个解决方案是在我的 DataSet 中创建一个 dt1 的副本,并将过滤后的版本存储在其中,比如 FilteredDt1,但是,我不想在内存中有冗余数据/DataRows。

根据我在 Microsoft 文档中阅读的内容,我认为在 DataView 的帮助下我可以做得更好,我将 DataView 作为第二个参数传递到 classes,但我不知道我该怎么做,也是从 软件架构 的角度来看。

遇到的问题

我是 ADO.NET 的新手,如果您纠正我,如果我的问题中有任何错误/不正确的假设,我将非常感激。

你可以使用 linq:

var filtered1 = MyDataSet.Tables["d1"].Rows.OfType<DataRow>()
                .Where(r => r["Column"] = value);

var filtered2 = MyDataSet.Tables["d1"].Rows.OfType<DataRow>()
                .Where(r => r["OtherColumn"] = differentValue);

现在 filtered1 将 return 一个 IEnumerable<DataRow> 其中 Column = value,
filtered2 将 return 一个 IEnumerable<DataRow> 其中 OtherColumn = differentValue,

而你的原始数据table保持不变。

请注意,在使用 Where 扩展方法之前,我必须使用 OfType 扩展方法,因为 Rows 属性 的类型为 DataRowCollection 不实现通用 IEnumerable<T> 接口,仅实现 not-generic IEnumerable(和 ICollection)接口。

更新:

寻找一种方法来 return 过滤数据 table 而不更改源数据 table 我遇到了 AsEnumerable DataTable 的扩展方法] class,其中 return 是 IEnumerable<DataRow>(),所以我的建议可以简化为 ...MyDataSet.Tables["d1"].AsEnumerable().Where...

另外,我找到了一种方法,可以让您创建仅包含过滤行的数据副本 table。您所做的是使用 DataView constructor that accepts DataTable, RowFilter, Sort, and DataViewRowState, and then call it's ToTable 方法 return 新数据 table.
请注意,这将为内存中的数据行创建新副本,因为 DataRow 只能属于单个 DataTable.

但是,请注意,我建议使用 IEnumerable<T>,其中 T 是您创建为 DTO 的特定类型,而不是直接使用 DataTable。这将使您的生活更加安全和轻松。