C#.NET 大型企业信息化系统集成快速开发平台 4.2 版本 - 大型软件系统客户端数据同步的问题解决
2015-02-07 13:04 通用C#系统架构 阅读(4261) 评论(0) 编辑 收藏 举报作为一个完整的整体信息化解决方案需要有足够强大的各种功能,这些功能相对独立,又互相依存。当有需要这样的功能时可以随时拿出来用,适当修改一下就可以满足要求。只有这样才能快速开发各种信息化系统,才能满足各种客户的需求。
同步数据需要解决的问题主要有:
01:全国性大型集团公司的信息化改造项目会涉及到非常多的分公司网点的客户端需要同步数据的各种需求,这个已经超越了人工能处理好的极限。
02:网点非常多时,往往由于业务的特殊性会有能离线作业的需要,网络故障、网络带宽不理想时都可以进行离线处理的工作流程需要。
03:也由于网络安全原因、工作特殊原因,必须有些数据需要在本地网络里处理好,然后通过特殊专线等进行定时上传上报业务数据。
04:手持移动设备等、由于工作环境没有实时的互联网条件、可能也需要在离线条件下处理好数据,连接上网络时再把数据上传到总部。
05:有从大型数据库同步到桌面数据库的需要,例如服务器是SQLServer的、客户端是SQLite的。
06:也有可能是服务器与服务器之间的数据同步,例如生产主要数据库同步到统计数据库,同步到查询数据库里。
07:服务器上的总部数据库可能很庞大,每个网点可能只需要同步部分数据库,甚至是特殊限制的sql语句获取的数据部分需要同步。
08:若需要同步的数据比较多时,由于网络带宽、服务器的稳定性考虑,需要有提供批次获取数据的功能,可以分批获取数据。
09:表结构有变动时;有增加、有减少、有变更是、不要有问题故障发生;可以平稳升级、可以平稳同步数据。
10:若有上万信息终端,若没有数据就不需要进行任何sql语句查询了,减轻中心数据库查询压力。
11:可以访问的库、允许同步的表进行权限控制,防止越权获取不应该看到的数据。
12:接口调用的安全性保证、如何防止恶意调用等,对一个对外开放的接口,这些都需要考虑风险。
13:升级同步还可以能灵活扩展、能执行SQL语句,能编写C#逻辑控制代码。
14:同步程序可以在后台进行、不影响主要业务功能、不影响业务操作。
15:代码简洁、好维护、好调试、好改进,好快速增加同步额外的数据表等。
参考代码如下:
//----------------------------------------------------------------- // All Rights Reserved , Copyright (C) 2015 , Hairihan TECH, Ltd. //----------------------------------------------------------------- using System; using System.Collections.Specialized; using System.Data; using System.Net; using System.Text; using Newtonsoft.Json; namespace DotNet.Win { using DotNet.Business; using DotNet.Utilities; /// <summary> /// 数据同步类 /// </summary> public partial class Synchronous { /// <summary> /// 远程数据同步的工具类 /// </summary> /// <param name="fromDataBase">从服务器的哪个数据库获取数据</param> /// <param name="tableName">同步哪个表</param> /// <param name="primaryKeys">表的主键是什么</param> /// <param name="modifiedOn">同步的更新时间</param> /// <param name="toDataBaseDbType">同步到本地什么类型的数据库里?</param> /// <param name="dbConnection">同步的目标数据库连接方式?</param> /// <returns>影响行数</returns> public static int SynchronousTable(string fromDataBase, string tableName, string[] primaryKeys, DateTime? modifiedOn, CurrentDbType toDataBaseDbType, string dbConnection) { int result = 0; // 输入参数检查 if (primaryKeys == null) { return result; } int topLimit = 200; DataTable dataTable = null; IDbHelper dbHelper = null; dbHelper = DbHelperFactory.GetHelper(toDataBaseDbType, dbConnection); SQLBuilder sqlBuilder = new SQLBuilder(dbHelper); while (topLimit == 200) { string url = BaseSystemInfo.WebHost + "WebAPIV42/API/Synchronous/GetTopLimitTable"; WebClient webClient = new WebClient(); NameValueCollection postValues = new NameValueCollection(); postValues.Add("userInfo", BaseSystemInfo.UserInfo.Serialize()); postValues.Add("systemCode", BaseSystemInfo.SystemCode); postValues.Add("securityKey", BaseSystemInfo.SecurityKey); postValues.Add("dataBase", fromDataBase); postValues.Add("tableName", tableName); postValues.Add("topLimit", topLimit.ToString()); postValues.Add("modifiedOn", modifiedOn.Value.ToString(BaseSystemInfo.DateTimeFormat)); // 向服务器发送POST数据 byte[] responseArray = webClient.UploadValues(url, postValues); string response = Encoding.UTF8.GetString(responseArray); if (!string.IsNullOrEmpty(response)) { dataTable = (DataTable)JsonConvert.DeserializeObject(response, typeof(DataTable)); } int r = 0; // 出错的日志都需要能保存起来,这样有问题的可以找出原因来。 for (r = 0; r < dataTable.Rows.Count; r++) { // 先删除数据,修改的、新增的、都删除后添加来处理,问题就简单化了 // dbHelper.ExecuteNonQuery("DELETE FROM " + tableName + " WHERE " + primaryKey + " = '" + dataTable.Rows[r][primaryKey].ToString() + "'"); sqlBuilder.BeginDelete(tableName); for (int i = 0; i < primaryKeys.Length; i++) { string primaryKey = primaryKeys[i]; if (string.IsNullOrWhiteSpace(primaryKey)) { sqlBuilder.SetWhere(primaryKey, dataTable.Rows[r][primaryKey].ToString()); } } sqlBuilder.EndDelete(); // 然后插入数据 sqlBuilder.BeginInsert(tableName); for (int i = 0; i < dataTable.Columns.Count; i++) { // 这里能判断目标表里是否有这个字段存在就更完美了。 sqlBuilder.SetValue(dataTable.Columns[i].ColumnName, dataTable.Rows[r][dataTable.Columns[i].ColumnName]); } sqlBuilder.EndInsert(); if (DateTime.Parse(dataTable.Rows[r][BaseBusinessLogic.FieldModifiedOn].ToString()) > modifiedOn.Value) { modifiedOn = DateTime.Parse(dataTable.Rows[r][BaseBusinessLogic.FieldModifiedOn].ToString()); } result++; } topLimit = dataTable.Rows.Count; } return result; } } }