using CnasSynchronousCommon; using CnasSynchronusClient; using CnasSynchrousModel; using System; using System.Collections.Generic; using System.Data; using System.IO; using System.Linq; using System.Text; using System.Timers; using System.Xml.Serialization; namespace CNAS_SyncService { public class SyncServiceOperation { System.Timers.Timer timerSync; ServiceConfig config = new ServiceConfig(); bool bRunComplete = true; int WaitCount = 0; string strNowDate = ""; FileWatcherOperation fileWatcherOperation; public void Start() { AppLog.ServiceInfo("SyncSerivce:服务启动"); //读取全局配置信息 SystemFormatConfig systemFormat = FileOperation.GetSystemFormatConfigData(); GlobalCommonOperation.strStartGeneralVersion = systemFormat.StartGeneralVersion; GlobalCommonOperation.strStartWebApi = systemFormat.StartWebApi; GlobalCommonOperation.strWebApiUrl = systemFormat.WebApiUrl; GlobalCommonOperation.strTargetDbType = systemFormat.TargetDBType; //读取服务配置信息 config = ReadServiceConfigData(); AppLog.Error("打印日志1" + config.Minutes); timerSync_Elapsed(null,null); return; if (config.Minutes != 0) { //启动文件/文件夹监控 if (config.IfStartFileWatcher == "1") { fileWatcherOperation = new FileWatcherOperation(ReadSyncInstruments()); fileWatcherOperation.GetFileWatcherItems(); fileWatcherOperation.StartFileWatcher(); } // 启动定时器 timerSync = new System.Timers.Timer(); timerSync.Interval = config.Minutes * 60 * 1000; //设置计时器事件间隔执行时间 timerSync.Elapsed += new System.Timers.ElapsedEventHandler(timerSync_Elapsed); timerSync.Enabled = true; timerSync.AutoReset = true; } else { //写入日志 AppLog.ServiceInfo("SyncSerivce:未能成功读取定时器时间,本次同步失败。"); } } private void timerSync_Elapsed(object sender, ElapsedEventArgs e) { AppLog.ServiceInfo("定时器启动"); //如果等待执行次数超出最大数值,则认为当前正在执行出现未知名问题,直接回收当前执行,执行下次 if (WaitCount >= config.MaxWaitCount) { //回收垃圾 GC.Collect(); bRunComplete = true; } if (bRunComplete) { WaitCount = 0; //只要正常执行,等待标识都将恢复为0 bRunComplete = false; //清理过期日志 if (strNowDate != DateTime.Now.ToString("yyyyMMdd")) { AppLog.ServiceInfo("清理过期日志"); strNowDate = DateTime.Now.ToString("yyyyMMdd"); //删除日志文件 string logDays = FileOperation.GetSystemFormatConfigData().ShowLogDays; int logday; if (int.TryParse(logDays, out logday)) AppLog.DeleteLog(logday); } //执行同步程序 //1.读取配置信息 List lstSyncInstrument = ReadSyncInstruments(); //2 遍历仪器列表,逐个列表进行同步 foreach (var instrumentItem in lstSyncInstrument) { //如果是文件,使用FileSystemWatcher查看文件是否发生了变化 if (fileWatcherOperation != null && fileWatcherOperation.LstWatcherItems.Count > 0) { var watcherItem = fileWatcherOperation.LstWatcherItems.Where(p => p.SyncItemId == instrumentItem.GUID && p.SyncIfChanged == true).FirstOrDefault(); if (watcherItem!=null) { RunSyncByInstrument(instrumentItem,watcherItem); } else { AppLog.ServiceInfo("检测到文件/文件夹没有发生变化,跳过本次同步执行"); } } else { RunSyncByInstrument(instrumentItem); } } bRunComplete = true; //回收垃圾 GC.Collect(); } else { WaitCount++; AppLog.ServiceInfo($"等待标识:{WaitCount}"); } } private List ReadSyncInstruments() { List lstSyncInstrument = new List(); lstSyncInstrument = FileOperation.GetLocalSyncInStrumentData(); AppLog.ServiceInfo($"读取到本地配置信息行数{lstSyncInstrument.Count}"); return lstSyncInstrument; } private void RunSyncByInstrument(SyncInstrumentItemInfo syncInstrumentItem,FileWatcherItem fileWatcherItem=null) { //0.读取目标库表数据的最大时间 1.读取来源的数据 2.对读取到的数据进行逻辑处理,整理格式 3.执行同步 AppLog.ServiceInfo("准备根据日期字段查询筛选"); var query = syncInstrumentItem.LstSyncPramas.Where(s => s.IfDateField == true).ToList(); if (query.Count == 1) { string strCompareTime = ""; string strDateTime = CnasDataOperationFact.CnasDataOperation().GetMaxTimeByTableName(syncInstrumentItem.SyncTargetDBInfo, syncInstrumentItem.LstSyncPramas[0].TargetTable, query[0].TargetField, syncInstrumentItem.CnasInstrumentColumn,syncInstrumentItem.GUID); //strDateTime = "2016-07-01 00:00:00"; if (strDateTime == "1899-1-1") { AppLog.ServiceInfo($"读取上次最晚执行时间失败,请检查原因。"); return; } else if (strDateTime == "") { strCompareTime = Convert.ToDateTime(config.InitalDT.ToString()).ToString("yyyy-MM-dd HH:mm:ss"); } else strCompareTime = Convert.ToDateTime(strDateTime).AddDays(-3).ToString("yyyy-MM-dd HH:mm:ss"); AppLog.ServiceInfo($"读取上次最晚执行时间为{strCompareTime}"); object[] obj = new object[] { syncInstrumentItem.LstSyncPramas[0].SourceTable, query[0].SourceField, strCompareTime }; AppLog.ServiceInfo($"准备构建数据源读取工厂"); InstrumentData instrumentData = InstrumentDataFact.CreateInstrumentDataSource(syncInstrumentItem.SyncInstrumentDSInfo, obj); AppLog.ServiceInfo($"构建数据源读取工厂完成,准备读取数据源"); DataTable dtReadySource = instrumentData.GetInstrumentDataByDate(); AppLog.ServiceInfo($"根据日期读取准备插入的来源数据,共{dtReadySource.Rows.Count}条数据"); string strErrorMsg = ""; RunUpLoad(syncInstrumentItem, dtReadySource, ref strErrorMsg); if (strErrorMsg != "") { //写入日志 AppLog.ServiceInfo(strErrorMsg); } else { if (fileWatcherItem != null) fileWatcherItem.SyncIfChanged = false; } } else { AppLog.ServiceInfo("SyncSerivce:未能成功读取日期字段,可能不存在或存在多个日期字段,本次同步失败。"); } } private void RunUpLoad(SyncInstrumentItemInfo syncInstrumentItem,DataTable dtReadySource,ref string strMsg) { //根据映射字段获取准备上传的所有数据 if (dtReadySource == null || dtReadySource.Rows.Count <= 0) return; //构建准备插入的数据 DataTable dtTarget = CnasDataOperationFact.CnasDataOperation().GetCNASTablesStruct(syncInstrumentItem.LstSyncPramas[0].TargetTable, syncInstrumentItem.SyncTargetDBInfo); AppLog.ServiceInfo("读取目标数据的数据结构"); if (dtTarget.Columns.Count <= 0) { strMsg="未能成功读取CNAS数据库列,请检查数据库配置。"; return; } CnasInsertOperation insertOperation = new CnasInsertOperation() { syncInstrumentItem = syncInstrumentItem }; AppLog.ServiceInfo("遍历所有来源数据,构造准备插入的数据"); strMsg=insertOperation.CreateInputData(dtReadySource, ref dtTarget); if (strMsg != "") return; if (dtTarget.Rows.Count <= 0) { strMsg = "创建准备插入的数据行为空。"; return; } AppLog.ServiceInfo("检查准备插入的数据是否合法"); insertOperation.CheckInsertDataFormat(dtTarget, ref strMsg); if (strMsg != "") return; //逐行执行插入 List lstError = new List(); int ErrorCount = 0; int SuccessCount = 0; int OtherCount = 0; AppLog.ServiceInfo($"逐行插入目标数据,最终准备插入(更新)数据行{dtTarget.Rows.Count}"); foreach (DataRow dr in dtTarget.Rows) { if (dr[11].ToString().Length > 1) { AppLog.Error($"逐行插入目标数据,最终准备插入(更新)数据行{dr[11]}"); dr[11] = kxjsf(dr[11].ToString()); } if (dr[12].ToString().Length > 1) { AppLog.Error($"逐行插入目标数据,最终准备插入(更新)数据行{dr[12]}"); } if (dr[13].ToString().Length > 1) { AppLog.Error($"逐行插入目标数据,最终准备插入(更新)数据行{dr[13]}"); } if (dr[14].ToString().Length > 1) { AppLog.Error($"逐行插入目标数据,最终准备插入(更新)数据行{dr[14]}"); } if (dr[15].ToString().Length > 1) { AppLog.Error($"逐行插入目标数据,最终准备插入(更新)数据行{dr[15]}"); } if (dr[16].ToString().Length > 1) { AppLog.Error($"逐行插入目标数据,最终准备插入(更新)数据行{dr[16]}"); } dr.AcceptChanges(); int iReturn = CnasDataOperationFact.CnasDataOperation().InsertDataToCNASTable(GlobalCommonOperation.ConvertDataRowToTable(dr), syncInstrumentItem.SyncTargetDBInfo, syncInstrumentItem.LstSyncPramas, syncInstrumentItem.CnasInstrumentColumn, syncInstrumentItem.lstFixedValue); if (iReturn <= 0) //此时出现问题 { if (iReturn == -1) { AppLog.ServiceInfo("数据库连接中断,终止本次上传。"); break; //此时数据库连接中断,直接跳出循环,结束本次数据同步传输 } else if (iReturn == -2) //等于-2表示插入准备更新时发现数据一致,不再执行 { OtherCount++; } else { ErrorCount++; //lstError.Add(GlobalCommonOperation.ConvertDataRowToTable(dr).Rows[0]); } } else { SuccessCount++; AppLog.Info("成功插入(更新)1条数据。"); } } AppLog.ServiceInfo($"上传操作完成!其中成功{SuccessCount}条,失败{ErrorCount}条,其他{OtherCount}条。............................................................................................................"); } private string kxjsf(string sss) { double sd = Convert.ToDouble(sss); //double sd = 123.123456; string temps2 = "0"; string temps3 = "0"; string temps4 = "0"; int tempi2 = 0; int tempi3 = 0; int tempi4 = 0; if (sss.Contains('.')) { string[] s1 = sss.Split('.'); if (s1[1].Length > 2) { if (s1[1].Length > 2) { temps2 = s1[1].Substring(1, 1); temps3 = s1[1].Substring(2, 1); } tempi2 = int.Parse(temps2); tempi3 = int.Parse(temps3); if (s1[1].Length > 3) { temps4 = s1[1].Substring(3, 1); } tempi4 = int.Parse(temps4); if (tempi3 > 5 || tempi3 < 5) { return sd.ToString("0.00"); } else { if (tempi4 != 0) { return sd.ToString("0.00"); } else { if (tempi2 == 0 || tempi2 == 2 || tempi2 == 4 || tempi2 == 6 || tempi2 == 8) { return sss.Substring(0, 5); } else { return sd.ToString("0.00"); } } } } } return sss; } private ServiceConfig ReadServiceConfigData() { ServiceConfig config = new ServiceConfig(); try { //读取本地文件中存储的配置信息 XmlSerializer serializer = new XmlSerializer(config.GetType()); FileStream stream = new FileStream(FileHelper.getBasePath() + "/DataConfig/SyncServiceData.xml", FileMode.Open); config = (ServiceConfig)serializer.Deserialize(stream); stream.Close(); } catch (Exception ex) { AppLog.ServiceInfo(ex.Message); } return config; } } }