What we want to do is group the rows by the distinct values. If we want to use LINQ against a DataTable, the easiest way is using the built-in DataTable.AsEnumerable()
extension method. This returns an IEnumerable<DataRow>
for you.
Once we've got that, we need to construct a comparable object out of the composite of the three values. Here I used the approach of string concatenation, because strings are easy to compare. There are other ways you could do this, but this one is simple:
name|phone|location
This produces a sequence of IGrouping<string, DataRow>
. Each grouping is also an IEnumerable<DataRow>
which represents the subset for that group. So if we sort each grouping object by time, and pull the first one off, that's the first row.
Here's the complete code.
var rows = dsHoldingSet.Tables["FileData"].AsEnumerable()
.GroupBy(row => string.Format("{0}|{1}|{2}",
row.Field<string>("name"),
row.Field<string>("phone"),
row.Field<string>("location"))
.Select(group =>
group.OrderBy(row => row.Field<TimeSpan>("time")).First());
Some other notes - phone
should be a string, not a long; unless time
represents some other kind of measure you haven't gone into, it should either be a TimeSpan or a DateTime. The first thing you want to do when loading a data set to manipulate is coerce data into their most robust and correct data types - it makes the actual manipulation MUCH easier. You can deconvert back if you need to after it's done.