Reputation: 211
I have 2 DataTables that looks like this:
YesterdaysTable
AAA
BBB
CCC
DDD
EEE
FFF
GGG
HHH
III
JJJ
TodaysTable
AAA
BBB
DDD
FFF
GGG
HHH
III
JJJ
As you can see, TodaysTable
does not contain CCC & EEE. When I try to find the differences to let me know what's in YesterdaysTable
that does not exist in TodaysTable
using the following code, I get an error:
InvalidOperationException: the source contains no DataRows
but there are rows in my source:
DataTable dtSource = new DataTable();
dtSource = yesterdaysTable.AsEnumerable().Except(todaysTable.AsEnumerable()).CopyToDataTable();
var difference = yesterdaysTable.AsEnumerable().Select(r => r.Field<string>("Apps")).Except(todaysTable.AsEnumerable().Select(r => r.Field<string>("Apps")));
if (difference.Any())
{
DataTable Table3 = (from row in todaysTable.AsEnumerable()
join app in difference on row.Field<string>("Apps") equals app
select row).CopyToDataTable();
}
I get the same error when I use similar code:
var appsNotInB = yesterdaysTable.AsEnumerable().Select(r => r.Field<string>("Apps"))
.Except(todaysTable.AsEnumerable().Select(r => r.Field<string>("Apps")));
var TableC = (from row in yesterdaysTable.AsEnumerable()
join id in appsNotInB on row.Field<string>("Apps") equals id
select row).CopyToDataTable();
I went as far as trying to write a nested for-loop to try to put the differences into a List<string>
object, to no avail:
for (int i = 0; i < yesterdaysTable.Rows.Count; i++)
{
for (int j = 0; j < todaysTable.Rows.Count; j++)
{
if (yesterdaysTable.Rows[i]["Apps"].ToString() != todaysTable.Rows[j]["Apps"].ToString())
{
//lstNoMatch.Add(yesterdaysTable.Rows[i]["Apps"].ToString());
lstNoMatch.Add(todaysTable.Rows[j]["Apps"].ToString());
}
}
}
I've tried a few different solutions but nothing is working and I don't want the post to be unnecessarily long. I've hit a dead-end :(
Any suggestions?
Upvotes: 0
Views: 900
Reputation: 460108
CopyToDataTable
throws this exception if the query didnt return any rows. One reason why i avoid that method. You could avoid the exception with pre-checking with query.Any()
. But that executes it twice. So a foreach
to add the rows is to be preferred.
I try to find the differences to let me know what's in
YesterdaysTable
that does not exist inTodaysTable
Then this query does the job (you've done this correctly):
var onlyYesterdayApps = yesterdaysTable.AsEnumerable()
.Select(r => r.Field<string>("Apps"))
.Except(todaysTable.AsEnumerable().Select(r => r.Field<string>("Apps")));
If you want the rows in a third table you have to use YesterdaysTable
as source:
DataTable result = yesterdaysTable.Clone(); // empty table with same columns
var yesterdayRows = from r in yesterdaysTable.AsEnumerable()
join app in onlyYesterdayApps
on r.Field<string>("Apps") equals app
select r;
foreach(DataRow row in yesterdayRows)
result.ImportRow(row); // import rows if the query above yielded rows
Just the final foreach
will execute the two queries(which are actually merged to one).
Upvotes: 1