Lee Grindon
Lee Grindon

Reputation: 2175

Sync two tables into one read table using Microsoft sync framework

I have two sql server tables which I would like to sync to a read sql database. I want to flatten the data from the source database into one table in the read database using the sync framework. Can I do this?

Upvotes: 0

Views: 546

Answers (3)

ufo
ufo

Reputation: 685

I'm trying to do the same, I suppose. This is my question on stackoverflow: Merging 2 tables in a single table with different schema

I worked on this problem for some times and I reached some results... For now, I'm working on the case in which the changes are only tracked in the PERSON table (so if something change in ADDRESS the changes are not synchronized). But I suppose the code can be improved to track changes in ADDRESS too... And for now I'm not taking into consideration the changes in the destination db (in CUSTOMER table). This will be more difficult to code, I suppose...

Anyway, my solution add an handler to changesSelected, there I alter the DataTable adding the columns I need (Address and City). I get the Address and the City by a sql SELECT and updates the rows... This works for updated and inserted rows... The problem raise with deleted rows. In my db CUSTOMER, the primary key must be Id-Address, and not only Id (or I can't have multiple ADDRESS for each PERSON). So, when SyncFX tries to perform a deletion, the keys don't match and the deletion doesn't affect any row... I don't know how to alter a DataRow with state deleted, and I also can't get the Address from the db... So I can't have an Id-Address information in the deleted DataRow... For now, I can only perform a sql DELETE using the Id (the only available info for a deleted row)...

Please try to improve the code and post back, so we could help each other!

This is the code. First the addhandler, then the code into the handler.

 AddHandler remoteProvider.ChangesSelected, AddressOf remoteProvider_ChangesSelected

...

Private Shared Sub remoteProvider_ChangesSelected(ByVal sender As Object, ByVal e As DbChangesSelectedEventArgs)

        If (e.Context.DataSet.Tables.Contains("PersonGlobal")) Then
            Dim person = e.Context.DataSet.Tables("PersonGlobal")

            Dim AddressColumn As New DataColumn("Address")
            AddressColumn.DataType = GetType(String)
            AddressColumn.MaxLength = 10
            AddressColumn.AllowDBNull = False
            'NULL is not allowed, so set a defaultvalue
            AddressColumn.DefaultValue = "Nessuna"

            Dim CityColumn As New DataColumn("City")
            CityColumn.DataType = GetType(String)
            CityColumn.AllowDBNull = False
            CityColumn.DefaultValue = 0

            persona.Columns.Add(AddressColumn)
            persona.Columns.Add(CityColumn)

            Dim newPerson = person.Clone()

            For i = 0 To person.Rows.Count - 1 Step 1

                Dim row = person.Rows(i)

                If (row.RowState <> DataRowState.Deleted) Then
                    Dim query As String = "SELECT * FROM dbo.address WHERE Id = " & row("AddressId")

                    Dim sqlCommand As New SqlCommand(query, serverConn)
                    serverConn.Open()
                    Dim reader As SqlDataReader = sqlCommand.ExecuteReader()
                    Try
                        While reader.Read()
                            row("Address") = CType(reader("Address"), String)
                            row("City") = CType(reader("City"), String)
                            ' Solo importando mantengo i valori di RowState
                            newPerson.ImportRow(row)
                        End While
                    Finally
                        reader.Close()
                    End Try
                    serverConn.Close()
                Else
                    ' TODO - Non funziona la cancellazione!!!
                    ' La cancellazione cerca la chiave primaria su cliente, che è ID-Via
                    ' Noi abbiamo l'ID corretto, ma "nessuna" come via...
                    ' Dobbiamo recuperare la via giusta...

                    Dim query As String = "DELETE FROM dbo.customer WHERE Id = " & row("Id", DataRowVersion.Original)

                    Dim sqlCommand As New SqlCommand(query, clientConn)
                    clientConn.Open()
                    sqlCommand.ExecuteNonQuery()
                    clientConn.Close()
                End If
            Next

            newPerson.Columns.Remove(newPerson.Columns("AddressId"))

            e.Context.DataSet.Tables.Remove(person)
            e.Context.DataSet.Tables.Add(newPerson)
        End If

    End Sub

Upvotes: 0

JuneT
JuneT

Reputation: 7860

if you're using the older providers (same one used by VS Local Database Cache Project item), you can use a view on the server side, however, your client can only be SQL Ce. but even that is tricky, what constitues a changed row if a change can occur on two source tables? if table 1 is updated and table 2 is not or vice versa?

the newer provider for SqlSyncProvider dont support views as its change tracking is based on triggers and the entire provisioning works against tables.

@Scott, schema's or table structures dont need to match.

Upvotes: 0

Scott Munro
Scott Munro

Reputation: 13596

The schemas in the source and target need to match. You could add a view that joins the two source tables within the source database and presents the data in the same format that your 'read' database expects.

Upvotes: 1

Related Questions