2

I need to Compare Two dataTables.
dataTable A contains current set of Data on clients machine.
dataTable B contains future updates to dataTable A.

dataTable A structure
ID | firstname  | lastName
 1 | "test"     | "last"
 2 | "whatever" | "someone"
 3 | "hi"       | "hello

dataTable B Structure
ID | firstname  | lastName
 1 | "updated"  | "yes"
 2 ->deleted
 3 | "hi"       | hello" ->unchanged
 4 | "new"      |record " ->row added

When I go dataTableA.merge(datatableB)

I basically just get dataTableA with dataTableB added rows so for example

ID | firstname  | lastName
 1 | "test"     | "last"
 2 | "whatever" | "someone"
 3 | "hi"       | "hello
 1 | "updated"  | "yes"
 3 | "hi"       | hello" ->unchanged
 4 | "new"      |record " ->row added

It doesn't match on the IDs and get updated or deleted. I just want to compare two tables, update table A that should look exactly like table B. I'm not quite sure how to accomplish this properly.

Basically there is a SQL table in the clients machine that needs to get completed updated and sync exact to a datatable B that is being passed in. In theory i just want to take table B and basically update table A. So after I need to update the SQL table. I tried something like this.

Dim adapter = New SqlDataAdapter("select * from test_table2", connection)
Using (New SqlCommandBuilder(adapter))
    adapter.Fill(dTable)
    connection.Open()
    adapter.Update(dTable)
End Using

Doesn't seem to work.

haraman
  • 2,744
  • 2
  • 27
  • 50
Sirus
  • 382
  • 1
  • 8
  • 35
  • @haraman The last line of your edit does not make sense. – Andrew Morton Oct 16 '15 at 17:45
  • Thanks for pointing out, just verified the edits, wonder from where that line came, because when I started editing it was already there. Corrected. – haraman Oct 16 '15 at 17:56
  • @Sirus Two separate datatables, they can not be directly merged like this. You can find good reference about datatables here [A-Practical-Guide-to-NET-DataTables-DataSets](http://www.codeproject.com/Articles/6179/A-Practical-Guide-to-NET-DataTables-DataSets-and) – haraman Oct 16 '15 at 18:27
  • ok... i just want to find a way how to syncronize two data tables. they are coming from different databases but they have the same schema. i want to analyze what needs to be different to update/edit/delete and then update the sql table.. seems like this is hard to find an easy way – Sirus Oct 16 '15 at 18:42
  • @Sirus Are the two databases in the same instance of SQL Server? Then you could do it all in SQL easily. If the databases can connect to each other then you can still do it in SQL: [What is the T-SQL syntax to connect to another SQL Server?](http://stackoverflow.com/q/125457/1115360) – Andrew Morton Oct 16 '15 at 18:52
  • no i'm passing a dataTable Object from a different server over a WCF web service and the client is receiving it. Then from there the client has code to compare to what he has on his machine and synchronize to the table that was just imported. – Sirus Oct 16 '15 at 19:26

2 Answers2

0

If the datatables are supposed to end up identical, instead of using

dataTableA.merge(datatableB)

Try

dataTableA=datatableB.Copy

Got this info from here https://msdn.microsoft.com/en-us/library/system.data.datatable.copy(v=vs.110).aspx

David Wilson
  • 4,369
  • 3
  • 18
  • 31
0

Your both datatables are being created separately, independent of each other. In this context you can use following DataTable and LINQ operations such as

  • Intersect to find matching rows in both DataTables,
  • Except to find unique rows only in one table
  • ImportRow to copy specific rows of one DataTable to another.
  • Copy to copy an entire datatable into another

It could be like this

Dim dtA As DataTable 'Your original Table A
Dim dtB As DataTable 'Your modified Table B
Dim dtC As DataTable 'Unchanged Rows
Dim dtD As DataTable 'Final synchronized Table
Dim dtE As DataTable 'Deleted Rows

'Populate your Table A and Table B into dtA and dtB

'get unchanged rows into dtC (all rows - changed - deleted)
dtC = dtA.AsEnumerable.Intersect(dtB.AsEnumerable, DataRowComparer.Default).CopyToDataTable

'Copy all unchanged rows to final table
dtD = dtC.Copy

'Copy the structure to blank datatable
dtE = dtC.Clone

'process modified rows (changed + deleted) i.e. (all rows - unchanged rows)
For Each cdRow As DataRow In dtA.AsEnumerable.Except(dtC.AsEnumerable, DataRowComparer.Default).CopyToDataTable.Rows
    'check if this row exists in modified rows
    If dtB.Select("cid = " & cdRow.Item("cid").ToString).Count > 0 Then
        'This is a modified row copy it to the final table or process it to database
        dtD.ImportRow(dtB.Select("cid = " & cdRow.Item("cid").ToString).CopyToDataTable.Rows(0))
    Else
        'This is a deleted row copy it to the deleted records table or process it directly to the database
        dtE.ImportRow(cdRow)
    End If
Next
'Now dtE contains your deleted rows
'Finally dtD is your synchronized datatable

Assumptions and other details:

  • All DataTables should have same table structure
  • This code assumes that ID column is unique to identify new and old rows.
  • You will still have to process deleted rows (dtE) from original database.
  • DataTable dtD, dtE can be avoided, but just for the purpose of simplicity and better understanding of the concept these are included.
  • Instead of later processing all records in dtD and dtE in a separate loop you can directly update them to the database as mentioned in code above.
  • There may be memory, resources, processing/timing related issues in case you are processing large DataTables
haraman
  • 2,744
  • 2
  • 27
  • 50
  • ok i tried it.. i got an exception on the line. dtC = dtA.AsEnumerable.Intersect(dtB.AsEnumerable).CopyToDataTable Additional information: The source contains no DataRows. – Sirus Oct 16 '15 at 21:29
  • I have not implemented any exception handling yet. Don't you think that exception message is clear `Additional information: **The source contains no DataRows**`. Check if dtB has any records fetched from Table B – haraman Oct 16 '15 at 21:34
  • i realize that.. it is clear.. but it has data. i know that for a fact – Sirus Oct 16 '15 at 21:36
  • It's definitely a blank DataTable error. In the code above dtA and dtB must NOT be blank. To hande such case you can get cues from http://stackoverflow.com/a/7822056/5104101 as in `var dt = rows.Any() ? rows.CopyToDataTable() : table.Clone();` – haraman Oct 16 '15 at 21:49
  • Dim query = From a In dtReturnTable Group Join b In dtz On a.Item(0) Equals b.Item(0) Into g = Group Where g.Count = 0 Select a – Sirus Oct 16 '15 at 21:57
  • i just did another linq query to get the ids that were different on the datatables and that worked... so i don't know about that error cuz theres data there – Sirus Oct 16 '15 at 21:57
  • @Sirus I just created a test project to verify the above code and found that Intersect and Except are ignoring the default equality comparer, which they should not have [MSDN](https://msdn.microsoft.com/en-us/library/vstudio/bb300779(v=vs.100).aspx). I tested with their overloads using `DataRowComparer.Default` as parameter which works fine. Also there was a mistake in `dtD.ImportRow`. Check updated code. – haraman Oct 17 '15 at 23:59