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;
        }
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM