読み取りSQLデータベースに同期したい2つのSQLサーバーテーブルがあります。同期フレームワークを使用して、ソース データベースのデータを読み取りデータベースの 1 つのテーブルにフラット化したいと考えています。これはできますか?
3 に答える
ソースとターゲットのスキーマは一致する必要があります。ソースデータベース内の2つのソーステーブルを結合し、「読み取り」データベースが期待するのと同じ形式でデータを表示するビューを追加できます。
古いプロバイダー(VSローカルデータベースキャッシュプロジェクトアイテムで使用されているものと同じ)を使用している場合は、サーバー側でビューを使用できますが、クライアントはSQLCeのみになります。しかし、それでも注意が必要ですが、2つのソーステーブルで変更が発生する可能性がある場合、変更された行を構成するものは何でしょうか。表1が更新され、表2が更新されていない場合、またはその逆の場合はどうなりますか?
SqlSyncProviderの新しいプロバイダーは、変更の追跡がトリガーに基づいており、プロビジョニング全体がテーブルに対して機能するため、ビューをサポートしていません。
@ Scott、スキーマまたはテーブル構造は一致する必要はありません。
私も同じことをしようとしていると思います。これはスタックオーバーフローに関する私の質問です: Merging 2 tables in a single table with different schema
私はこの問題に何度か取り組み、いくつかの結果に達しました...今のところ、変更がPERSONテーブルでのみ追跡されるケースに取り組んでいます(したがって、ADDRESSで何かが変更された場合、変更は同期されません) . しかし、ADDRESSの変更も追跡するようにコードを改善できると思います...そして今のところ、宛先データベース(CUSTOMERテーブル)の変更は考慮していません。これはコーディングがより困難になると思います...
とにかく、私のソリューションは、changesSelected にハンドラーを追加します。そこで、必要な列 (Address と City) を追加して DataTable を変更します。SQL SELECT によって住所と市区町村を取得し、行を更新します...これは、更新された行と挿入された行に対して機能します...削除された行で問題が発生します。私の db CUSTOMER では、主キーは Id-Address である必要があり、Id だけではありません (または、PERSON ごとに複数の ADDRESS を持つことはできません)。そのため、SyncFX が削除を実行しようとすると、キーが一致せず、削除はどの行にも影響しません...状態が削除された DataRow を変更する方法がわかりません。データベースからのアドレス...したがって、削除されたDataRowにId-Address情報を含めることはできません...今のところ、Idを使用してSQL DELETEのみを実行できます(削除された行でのみ利用可能な情報).. .
コードを改善して投稿してください。お互いに助け合うことができます。
これがコードです。最初に addhandler、次にコードをハンドラーに挿入します。
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