C#.NET 大型企业信息化系统集成快速开发平台 4.2 版本 - 大型软件系统客户端数据同步的问题解决
作为一个完整的整体信息化解决方案需要有足够强大的各种功能,这些功能相对独立,又互相依存。当有需要这样的功能时可以随时拿出来用,适当修改一下就可以满足要求。只有这样才能快速开发各种信息化系统,才能满足各种客户的需求。
同步数据需要解决的问题主要有:
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; } } }
相关文章
- 使用Commons Logging
- 记一次 .NET 某自动化采集软件 崩溃分析
- [C# 中的序列化与反序列化](.NET 源码学习)
- .NET 向量类型的运算结果范例——用于学习Vector类所提供百多个向量方法
- 树莓派(香橙派)通过.NET IoT 操作SPI编写屏幕驱动 顺手做个四足机器人(一)
- WPF自定义控件之消息提示
- .NET跨平台框架选择之一 - Avalonia UI
- 篇(16)-Asp.Net Core入门实战-权限管理之用户创建与关联角色(ViewModel再用与模型验证二)
- 学习ASP.NET Core Blazor编程系列十——路由(下)
- 代码生成器(CodeBuilder) 2.9.4 稳定版
- 篇(15)-入门实战-权限管理之用户创建与关联角色(ViewModel再用与模型验证一)
- 篇(14)-Asp.Net Core入门实战-权限管理之角色编辑和赋权(ViewModel-DTO初探)
- 算法-2 选择排序、冒泡排序、插入排序
- 篇(13)-Asp.Net Core入门实战-将功能代码增加异步功能Async和配置简单防范CSRF攻击
- NET 6 实现滑动验证码(一)、创建工程
- 算法-1 算法复杂度
- 在WPF中使用Prism弹出自定义窗体样式的对话框
- 使用Fody时,CS-SCRIPT动态代码无法找到程序集
- C# 使用SIMD向量类型加速浮点数组求和运算(3):循环展开
- aspnetcore两种上传图片(文件)的方式