I have a DataSet
containing 4 DataTable
s, say dt1
, dt2
, dt3
, dt4
. I also have 3 DataRelation
s like this:
|Parent|Child|
| d1 | d2 |
| d2 | d3 |
| d2 | d4 |
My MasterClass
passes this DataSet
to several classes, each class needs to perform different actions using the DataSet
. However, before passing the DataSet
, MasterClass
needs to perform a filter on dt1
, as each class needs to work with the filtered version of dt1
. Note that I can't update dt1
, as I need to perform different filters on the same DataTable
. In the picture below, I try to visualize the structure:
My question is: What is the best way to pass the filtered dt1
to Class A..B
?
The first solution that I thought of, was to create a copy of dt1
in my DataSet
, and store the filtered version in it, say FilteredDt1
, however, I don't want to have redundant data / DataRow
s in memory.
From what I've read in docs from Microsoft, I think that I can do better with the help of a DataView
, in a way that I pass the DataView
as a second parameter to the classes, but I didn't get how I can do it, also from software architecture point of view.
Problems that I met:
DataRelation
s, if I use a DataView
?DataView
and a DataTable
?I am rather new to ADO.NET
, and I'd appretiate it very much, if you correct me, if there are any mistakes / incorrect assumptions in my question.
You could use 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);
Now filtered1
will return an IEnumerable<DataRow>
where Column = value
,
And filtered2
will return an IEnumerable<DataRow>
where OtherColumn = differentValue
,
And your original data table is left unchanged.
Note that I had to use the OfType
extension method before I could use the Where
extension method, since the Rows
property is of type DataRowCollection
that does not implement the generic IEnumerable<T>
interface, only the not-generic IEnumerable
(and ICollection
) interface.
Update:
Looking for a way to return a filtered data table without changing the source data table I came across the AsEnumerable
extension method for the DataTable
class, which returns an IEnumerable<DataRow>()
, so my suggestion can be simplified to ...MyDataSet.Tables["d1"].AsEnumerable().Where...
.
Also, I've found a way for you to create copies of the data table with only the filtered rows. What you do is use the DataView
constructor that accepts DataTable
, RowFilter
, Sort
, and DataViewRowState
, and then call it's ToTable
method to return a new data table.
Please note that this will create new copies for the data rows in memory, since a DataRow
can only belong to a single DataTable
.
However, Please note I would advise working with IEnumerable<T>
, where T
is specific types you creates as DTOs rather then working with directly DataTable
. That will make your life much safer and easier.