做爲一個完整的總體信息化解決方案須要有足夠強大的各類功能,這些功能相對獨立,又互相依存。當有須要這樣的功能時能夠隨時拿出來用,適當修改一下就能夠知足要求。只有這樣才能快速開發各類信息化系統,才能知足各類客戶的需求。web
同步數據須要解決的問題主要有:sql
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; } } }