Author:水如烟
总目录:行政区划数据方案设计
上一篇,行政区划程序的设计(十三)
在上面的测试中,我感觉某些类还是混乱。为此,有必要先理顺一下。
混乱的起源在于处理几个表的集合。为此,我在LzmTW上建一个泛型类,专门处理这种表集合。
类DataTableCollection,三个文件:
DataTableCollection.vb
Public Class DataTableCollection( Of T As DataTable)
Private gDataSet As New DataSet
Private gTableNameList As New List( Of String )
' 引入只读集合,不对外公开gDataSet和gTableNameList
Public ReadOnly Property DataTables() As System.Collections.ObjectModel.ReadOnlyCollection( Of T)
Get
Dim mTableList As New List( Of T)
For Each table As DataTable In gDataSet.Tables
mTableList.Add( CType (table, T))
Next
Return New System.Collections.ObjectModel.ReadOnlyCollection( Of T)(mTableList)
End Get
End Property
Public ReadOnly Property TableNames() As System.Collections.ObjectModel.ReadOnlyCollection( Of String )
Get
Return New System.Collections.ObjectModel.ReadOnlyCollection( Of String )(gTableNameList)
End Get
End Property
Public ReadOnly Property IsEmpty() As Boolean
Get
Return (gTableNameList.Count = 0 )
End Get
End Property
Public ReadOnly Property Item( ByVal tableName As String ) As T
Get
If Not Contains(tableName) Then Return Nothing
Return CType (gDataSet.Tables(tableName), T)
End Get
End Property
Public Function Contains( ByVal tableName As String ) As Boolean
Return gTableNameList.Contains(tableName)
End Function
' '' <summary>
' '' DataTable的相互转换
' '' </summary>
' '' <typeparam name="S">源表类型</typeparam>
' '' <typeparam name="D">目标表类型</typeparam>
' '' <param name="table">源表</param>
' '' <remarks>返回目标表的新实例并保留源表的表名</remarks>
Public Shared Function Convert( Of S As DataTable, D As DataTable)( ByVal table As S) As D
Dim mResult As D
mResult = CType (System.Activator.CreateInstance( GetType (D)), D)
mResult.TableName = table.TableName ' 保留源表的表名
' 公共的列名,不考虑列的类型是否相同
Dim mCommonColumns( - 1 ) As String
For Each column As DataColumn In table.Columns
If mResult.Columns.Contains(column.ColumnName) Then
uCollections.CommonServices.Append( Of String )(mCommonColumns, column.ColumnName)
End If
Next
' 如果没有公共的列,则返回一个空表
If mCommonColumns.Length = 0 Then Return mResult
' 不处理键值,如不符,会发生异常
Dim mResultRow As DataRow
For Each row As DataRow In table.Rows
mResultRow = mResult.NewRow
For Each column As String In mCommonColumns
mResultRow(column) = row(column)
Next
mResult.Rows.Add(mResultRow)
Next
mResult.AcceptChanges()
Return mResult
End Function
End Class
End Namespace
DataTableCollection.Methods.vb
Partial Class DataTableCollection( Of T As DataTable)
Public Sub Clear()
For Each tableName As String In gTableNameList
Dim tmpTable As DataTable = gDataSet.Tables(tableName)
gDataSet.Tables.Remove(tmpTable)
tmpTable.Dispose()
Next
gTableNameList.Clear()
End Sub
Public Sub Remove( ByVal tableName As String )
If Not Contains(tableName) Then Exit Sub
Dim tmpTable As DataTable = gDataSet.Tables(tableName)
gDataSet.Tables.Remove(tmpTable)
tmpTable.Dispose()
gTableNameList.Remove(tableName)
End Sub
Public Sub Add( ByVal table As DataTable)
Dim tmpTable As T = Convert( Of DataTable, T)(table)
Add(tmpTable)
End Sub
Public Sub Add( ByVal table As T)
AddTable(table)
End Sub
Private Sub AddTable( ByVal table As T)
' 如果已存在,则去除
Dim tmpTableName As String = table.TableName
Remove(tmpTableName)
gDataSet.Tables.Add(table)
gTableNameList.Add(tmpTableName)
End Sub
End Class
End Namespace
DataTableCollection.Local.vb
Partial Class DataTableCollection( Of T As DataTable)
Public Sub WriteXml( ByVal fileName As String )
gDataSet.WriteXml(fileName)
End Sub
Public Sub ReadXml( ByVal fileName As String )
If Not IO.File.Exists(fileName) Then
Throw New IO.FileNotFoundException( " 文件不存在 " , fileName)
End If
Dim tmpDataSet As New DataSet
tmpDataSet.ReadXml(fileName)
' 对数据集gDataSet作追加处理
For Each table As DataTable In tmpDataSet.Tables
Me .Add(table)
Next
tmpDataSet.Dispose()
End Sub
End Class
End Namespace
上面用到的一个函数uCollections.CommonServices.Append,是:
CommonServices.vb
Public Class CommonServices
Private Sub New ()
End Sub
Public Shared Sub Append( Of T)( ByRef collection As T(), ByVal value As T)
ReDim Preserve collection(collection.Length)
collection(collection.Length - 1 ) = value
End Sub
End Class
End Namespace
处理情况如下:
当引进类DataTableCollection后,在RegionalCommon项目上,
用来保存网上数据的数据集处理类NetDownloadLocalDataSet可以修改为
Public Class NetDownloadLocalDataSet
Inherits LzmTW.uSystem.uData.DataTableCollection( Of dsNetDownload.RegionalCodeDataTable)
End Class
End Namespace
用来保存准备更新到数据库的数据集的处理类UpdateDatabaseDataSet修改为
Public Class UpdateDatabaseDataSet
Inherits LzmTW.uSystem.uData.DataTableCollection( Of dsUpdateDatabase.RegionalCodeDataTable)
Public ReadOnly Property DataSet() As DataSet
Get
Dim mResult As New DataSet
Dim tmpTable As dsUpdateDatabase.RegionalCodeDataTable
For Each table As dsUpdateDatabase.RegionalCodeDataTable In Me .DataTables
tmpTable = LzmTW.uSystem.uData.CommonServices.TableConverter( Of dsUpdateDatabase.RegionalCodeDataTable, dsUpdateDatabase.RegionalCodeDataTable)(table)
mResult.Tables.Add(tmpTable)
Next
mResult.AcceptChanges()
Return mResult
End Get
End Property
End Class
End Namespace
之后,结合两个接口,把处理更新的全部所需功能组合建一个基类UpdateDatabaseService,
UpdateDatabaseService.vb
Public Event ServiceMessage As ServiceMessageHandler
Public Event UpdateDatabaseCurrentPercent As ServiceProgressPercentHandler
' 下载服务
Private WithEvents gDownloadService As RegionalCodeCommon.Interface.IClientProvideServices
' 下载的数据保存在这里,它可以保存到本地文件,并可以读取出来
Private gNetDownloadLocalDataset As New Database.NetDownloadLocalDataSet
' 保存供更新的数据
Private gUpdateDatabaseDataset As New Database.UpdateDatabaseDataSet
' 更新服务
Private WithEvents gUpdateService As RegionalCodeCommon.Interface.IServerServices
' '' <param name="downloadService">网上数据下载服务</param>
' '' <param name="updateService">更新数据库服务</param>
Sub New ( ByVal downloadService As RegionalCodeCommon.Interface.IClientProvideServices, ByVal updateService As RegionalCodeCommon.Interface.IServerServices)
gDownloadService = downloadService
gUpdateService = updateService
End Sub
Private Sub gDatasByDownload_ServiceMessage( ByVal sender As Object , ByVal message As String ) _
Handles gDownloadService.ServiceMessage, gUpdateService.ServiceMessage
RaiseEvent ServiceMessage(sender, message)
End Sub
Private Sub gUpdateDatabaseService_UpdateDatabaseCurrentPercent( ByVal sender As Object , ByVal currentPercent As Integer ) _
Handles gUpdateService.UpdateDatabaseCurrentPercent
RaiseEvent UpdateDatabaseCurrentPercent(sender, currentPercent)
End Sub
Public Sub Dispose()
gDownloadService.Dispose()
gUpdateService.Dispose()
End Sub
Protected Overrides Sub Finalize()
Me .Dispose()
MyBase .Finalize()
End Sub
Private Sub SendMessage( ByVal message As String )
RaiseEvent ServiceMessage( Nothing , message)
End Sub
End Class
UpdateDatabaseService.Prepare.vb
' 数据的取得有两种,一是从网上下载,二是从本地文件读取
' ******以下从本地读取******
Public Sub Load( ByVal filename As String )
SendMessage( String .Format( " 正读取文件数据:{0} " , filename))
Me .gNetDownloadLocalDataset.ReadXml(filename)
SendMessage( " 待命 " )
End Sub
Public Sub Save( ByVal filename As String )
SendMessage( String .Format( " 正保存数据至本地文件:{0} " , filename))
Me .gNetDownloadLocalDataset.WriteXml(filename)
SendMessage( " 待命 " )
End Sub
Public ReadOnly Property LocalCurrentVersionDates() As System.Collections.ObjectModel.ReadOnlyCollection( Of String )
Get
Return Me .gNetDownloadLocalDataset.TableNames
End Get
End Property
Public ReadOnly Property LocalCurrentRegionalCodeTables() As System.Collections.ObjectModel.ReadOnlyCollection( Of Database.dsNetDownload.RegionalCodeDataTable)
Get
Return Me .gNetDownloadLocalDataset.DataTables
End Get
End Property
Public ReadOnly Property LocalRegionalCodeTable( ByVal versionDate As String ) As Database.dsNetDownload.RegionalCodeDataTable
Get
Return Me .gNetDownloadLocalDataset.Item(versionDate)
End Get
End Property
' ******以下从网上下载********
' '' <summary>
' '' 下载版本信息
' '' </summary>
' '' <remarks></remarks>
Public Sub DownloadVerionDateInformations()
Me .gDownloadService.DownloadNetDataVersions()
End Sub
' '' <summary>
' '' 网上现有的数据版本
' '' </summary>
Public ReadOnly Property NetVersionDates() As String ()
Get
Dim mResult( - 1 ) As String
For Each row As Database.dsNetDownload.DownloadInformationsRow In Me .gDownloadService.NetDownloadInformationsTable
LzmTW.uSystem.uCollections.CommonServices.Append( Of String )(mResult, row.VersionDate)
Next
Return mResult
End Get
End Property
' '' <summary>
' '' 下载指定版本日期的区划码数据
' '' </summary>
' '' <param name="versiondate">版本日期</param>
Public Sub DownloadRegionalCodeDatas( ByVal versiondate As String )
Me .gDownloadService.DownLoadNetRegionalCodeDatas(versiondate)
If Not Me .gDownloadService.NetRegionalCodeTableDictionary.ContainsKey(versiondate) Then Exit Sub
' 将数据加到gNetDownloadLocalDataset里去
Me .gNetDownloadLocalDataset.Add( Me .gDownloadService.NetRegionalCodeTableDictionary(versiondate))
SendMessage( " 待命 " )
End Sub
' '' <summary>
' '' 下载全部版本数据
' '' </summary>
Public Sub DownloadRegionalCodeDatasAll()
Me .gDownloadService.DownLoadNetRegionalCodeDatasAll()
' 将数据加到gNetDownloadLocalDataset里去
For Each table As DataTable In Me .gDownloadService.NetRegionalCodeTableDictionary.Values
Me .gNetDownloadLocalDataset.Add(table)
Next
SendMessage( " 待命 " )
End Sub
End Class
UpdateDatabaseService.Update.vb
' '' <summary>
' '' 清空更新用数据集
' '' </summary>
Public Sub UpdateDataSetClear()
Me .gUpdateDatabaseDataset.Clear()
End Sub
' '' <summary>
' '' 当前将更新的版本
' '' </summary>
Public ReadOnly Property VersionDatesForUpdate() As System.Collections.ObjectModel.ReadOnlyCollection( Of String )
Get
Return Me .gUpdateDatabaseDataset.TableNames
End Get
End Property
' '' <summary>
' '' 添加更新的版本
' '' </summary>
' '' <param name="versionDate">版本日期</param>
' '' <remarks></remarks>
Public Sub AppendTableToUpdate( ByVal versionDate As String )
If Not Me .gNetDownloadLocalDataset.Contains(versionDate) Then Exit Sub
Me .gUpdateDatabaseDataset.Add( Me .gNetDownloadLocalDataset.Item(versionDate))
End Sub
' '' <summary>
' '' 添加当前所有版本
' '' </summary>
Public Sub AppendTableAllToUpdate()
For Each table As DataTable In Me .gNetDownloadLocalDataset.DataTables
Me .gUpdateDatabaseDataset.Add(table)
Next
End Sub
' '' <summary>
' '' 更新到服务器
' '' </summary>
' '' <remarks></remarks>
Public Sub Update()
Me .gUpdateService.UpdateDatabase( Me .gUpdateDatabaseDataset)
SendMessage( " 待命 " )
End Sub
End Class
示意图:
最后,RegionalCodeCenter继承这个类来具体实现
UpdateDatabaseService.vb
Inherits RegionalCodeCommon.UpdateDatabaseServiceBase
Sub New ( ByVal connectionString As String )
MyBase .New( New Services.ClientServices, New Services.ServerServices(connectionString))
End Sub
End Class
现在代码清晰多了。
现在的方案代码:代码
下一篇,行政区划程序的设计(十五) ,实现获取区划信息功能_1。