You can use LINQ to combine two objects DataTablecorresponding to each column. Then grab IQueryableand find all the lines in the first two objects DataTablethat are not in IQueryable.
An example :
private void SampleSolution(DataTable dt1, DataTable dt2)
{
var results = from table1 in dt1.AsEnumerable()
join table2 in dt2.AsEnumerable() on table1.Field<int>("id") equals table2.Field<int>("id")
where table1.Field<int>("ColumnA") != table2.Field<int>("ColumnA") || table1.Field<int>("ColumnB") != table2.Field<int>("ColumnB") || table1.Field<String>("ColumnC") != table2.Field<String>("ColumnC")
select table1;
var matched = from table1 in dt1.AsEnumerable()
join table2 in dt2.AsEnumerable() on table1.Field<int>("ColumnA") equals table2.Field<int>("ColumnA")
where table1.Field<int>("ColumnB") == table2.Field<int>("ColumnB") || table1.Field<string>("ColumnC") == table2.Field<string>("ColumnC") || table1.Field<object>("ColumnD") == table2.Field<object>("ColumnD")
select table1;
var missing = from table1 in dt1.AsEnumerable()
where !matched.Contains(table1)
select table1;
}
The code above should work, although I have not tested it.
LINQ DataTable, LINQ DataTables.
LINQ, LINQ.