Si8
Si8

Reputation: 9225

How to compare two datatables and only check for the rows found

var qry = from r1 in dtCMS.AsEnumerable() //row count - 416
          from r2 in dtEcho.AsEnumerable() //row count - 175
          where
              r1.Field<string>("Name") == r2.Field<string>("Name")
          select r2;

DataTable dt1 = dtEcho.AsEnumerable().Except(qry).CopyToDataTable(); 

Error:

The source contains no DataRows.

How can I modify the code above so that the comparison will only happen for the rows in r2?

I would like two functions:

The code fails if the DataTable I am comparing against has more rows and hence it can't compare.

Upvotes: 0

Views: 124

Answers (2)

Reza Aghaei
Reza Aghaei

Reputation: 125197

CopyToDataTable will throw an InvalidOperationException if the source sequence does not contain any DataRow objects:

The source contains no DataRows.

Your code is OK in general and to solve the problem with minimum changes, the only thing that you should change is the way that you create the result.

Instead of using CopyToDataTable put results in the result table using a for loop. To do so, first you should create a clone of your second table.

var qry = from r1 in table1.AsEnumerable() //row count - 416
          from r2 in table2.AsEnumerable() //row count - 175
          where
              r1.Field<string>("Name") == r2.Field<string>("Name")
          select r2;


var dt = table2.Clone();
table2.AsEnumerable().Except(qry).ToList().ForEach(x =>
{
    dt.Rows.Add(x);
});
this.dataGridView1.DataSource = dt;

Upvotes: 2

Alexei - check Codidact
Alexei - check Codidact

Reputation: 23078

If I got right what you want, the code should look like this:

// setup
var dtCMS = new DataTable();
dtCMS.Columns.Add("ID", typeof(int));
dtCMS.Columns.Add("Name", typeof(String));

for (int i = 0; i < 416; i++)
    dtCMS.Rows.Add(i, "Name " + i);

var dtEcho = new DataTable();
dtEcho.Columns.Add("ID", typeof(int));
dtEcho.Columns.Add("Name", typeof(String));

for (int i = 400; i < 575; i++)
    dtEcho.Rows.Add(i, "Name " + i);

// convert to enumerables
var cmsEnum = dtCMS.AsEnumerable();
var echoEnum = dtEcho.AsEnumerable();

var CmsMinusEcho = cmsEnum.Where(cms => !echoEnum.Any(echo => echo.Field<String>("Name").Equals(cms.Field<String>("Name"))));
var EchoMinusCms = echoEnum.Where(echo => !cmsEnum.Any(cms => cms.Field<String>("Name").Equals(echo.Field<String>("Name"))));

// get DataTable with check
var CmsMinusEchoDt = CmsMinusEcho.Count() > 0 ? CmsMinusEcho.CopyToDataTable() : null;
var EchoMinusCmsDt = EchoMinusCms.Count() > 0 ? EchoMinusCms.CopyToDataTable() : null;

Upvotes: 1

Related Questions