1.数据。数据特点,各种各样的报文数据,包括农业气象观测报和实时自动站数据,这些数据有规则的存放在中心服务器,要做的是down下这些数据,通过本系统处理存入数据库,自动完成day数据统计。主要涉及数据的自动和手动处理,数据的自我统计;前台用到winform,后台用的Sql Server 2008.
2.winform。手动和自动区别不大,我是在自动处理的基础上稍加修改就有了手动处理程序,事实上手动比自动搞起来简单点,后面将说明why……。
①农业气象观测报,这里称为AB报。该报文种类几十个,这里用到17个,AB报只是总称,该大类下又细分为土壤的Soil(0~i) 、物候的Pheno(0~1)、作物的Crop(0~i)……,子分类下报文格式字段又五花八门。这里大概是用到了工厂模式,处理如下图:
通过对象制作工厂产生能够处理特定类型报文的Class 对象,这个对象类实现接口:ZABMessage0;ZABTypeHandler就是根据报文的标识符来产生对应的处理类,因此命名为CreateObj。由于这些处理类要做的操作基本一致,只是报文内容和格式稍异,因此考虑使用统一接口来实现,可以使前台winform代码简洁而方便维护,总共要处理17种文件,也就是说要写17个相关的类,如果不用接口统一来管理,一个人维护起来简直就是噩梦啊!!!如果不用对象制作工厂,那么前台的代码尽管引入了统一接口,仍旧会很臃肿,臃肿的原因在于:数据源数据分为17种,如果不用对象生产器,那么要做多少次逻辑判断,才可以确定我们需要一个什么样的类来处理该文件。下面是部分代码:
public ZABMessage0 CreateObj() { switch (keyStr) { case "METE-01": return (new Mete01_ZAB()); case "METE-02": return (new Mete02_ZAB()); case "PHENO-01": return (new Pheno01_ZAB()); ……
//w-外层记录段循环 for (int i = 1; i <= headerZAB._segments; i++) { line = reader.ReadLine();//关键字段部分 reading splitArr = line.Split(sep, StringSplitOptions.RemoveEmptyEntries); ZABTypeHandler abTypeHandler = new ZABTypeHandler(splitArr[0]); int rows = int.Parse(splitArr[1].Remove(splitArr[1].Length - 1));//记录的行数 for (int ii = 1; ii <= rows; ii++) {//每一行记录 入库 ZABMessage0 obj = abTypeHandler.CreateObj(); obj._ConStr = dbConfig.conStr; line = reader.ReadLine();// row reading obj._ContentZAB = line.Substring(0, line.Length - 1); obj._Header = headerZAB; obj.Analysis(); obj.InsertDB();//obj 提交到数据库 } reader.ReadLine();//读入END终结符 }//end w-外层记录段循环
②自动站报文处理。自动站小时报文处理要考虑的因素就比较多了:原始的数据比较多,可能漏报,需要做day统计分析,同时数据来源另一个FTP,该FTP定时同步一些数据到磁盘,会出现文件读写竞争的问题(该问题后期给 了我不少麻烦,开始没考虑到这个问题)。该FTP定时10分钟做一次同步下载更新,而我的自动处理程序一个小时内,每5分钟做一次处理,不会重复处理一个文件,就是这样,每小时仅仅上百个站点的数据文件仍出现了“抢”的现象,造成了数据库读写异常。其次,刚开始设计的界面由于运行提示信息不够,带来了bug分析信息缺乏,后来补充了数据库表及字段。
③数据库。不用说了数据库都基本使用存储过程完成,天统计大部分是由存储过程完成少部分是在前台代码完成的。值得总结的是,对于实时的数据录入,虽然代码不会出错,但是放入到实际环境中还是会出现一些未知的错误,这些错误或者是由于代码量太大了自己掌控不了而忽略的错误,或是受其它客观因素的影响,因此记录软件运行过程信息显得十分有必要了,通过辅助记录信息如log.table,或者error.table,可以清楚看到每个小时到底处理了哪些数据,哪些站点是漏报的,某个时间段处理了哪些数据,可以精确到某一分钟处理了哪些数据文件,这为我们错误定位有很好很好好的帮助作用。这里使用了作业流水号,通过该流水号,记录了每小时处理数量,处理的文件类型,开始时间,结束时间;数据表中记录每条记录生成时间,开始处理时间结束处理时间。因此设计数据库时,丰富的字段和表看起来多余实则相当有用的!!!
最大的心得是,有时候通过案例测试,看着很正确处理,把这些代码嵌入到整体中时,或者在实际运行时,总会有主客观的原因出现异常,因此要十分小心,考虑要周全些,其次不要怕数据库字段繁多,越丰富的信息越是对后期有帮助!