我有两个要同步到读取 sql 数据库的 sql server 表。我想使用同步框架将源数据库中的数据展平到读取数据库中的一个表中。我可以这样做吗?
3 回答
源和目标中的模式需要匹配。您可以添加一个视图来连接源数据库中的两个源表,并以您的“读取”数据库所期望的相同格式显示数据。
如果您使用的是较旧的提供程序(与 VS 本地数据库缓存项目项使用的相同),您可以在服务器端使用视图,但是,您的客户端只能是 SQL Ce。但即使这很棘手,如果两个源表上可能发生更改,什么构成更改的行?如果表 1 已更新而表 2 未更新,反之亦然?
SqlSyncProvider 的较新提供程序不支持视图,因为它的更改跟踪基于触发器,并且整个配置针对表工作。
@Scott,模式或表结构不需要匹配。
我想我也在尝试做同样的事情。这是我在stackoverflow上的问题: Merging 2 tables in a single table with different schema
我在这个问题上工作了一段时间,并取得了一些结果......现在,我正在研究仅在 PERSON 表中跟踪更改的情况(因此,如果 ADDRESS 中的某些更改不同步) . 但我想代码也可以改进以跟踪 ADDRESS 的变化......现在我没有考虑目标数据库(在 CUSTOMER 表中)的变化。这将更难以编码,我想......
无论如何,我的解决方案向 changesSelected 添加了一个处理程序,在那里我更改了 DataTable 添加我需要的列(地址和城市)。我通过 sql SELECT 获取地址和城市并更新行...这适用于更新和插入的行...删除行会引发问题。在我的 db CUSTOMER 中,主键必须是 Id-Address,而不仅仅是 Id(或者我不能为每个人拥有多个 ADDRESS)。因此,当 SyncFX 尝试执行删除时,键不匹配并且删除不会影响任何行...我不知道如何更改状态已删除的 DataRow,我也无法获得来自 db 的地址...所以我不能在已删除的 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