public static IEnumerable <HistoryData> LoadFromDatabase(DateTime start, DateTime end, short?ID = null) { using (var dataReader = DataHelper.Instance.ExecuteProcedureReader("READHDATA", DataHelper.CreateParam("@STARTTIME", SqlDbType.DateTime, start), DataHelper.CreateParam("@ENDTIME", SqlDbType.DateTime, end), DataHelper.CreateParam("@ID", SqlDbType.Int, (object)ID ?? DBNull.Value))) { if (dataReader == null) { yield break; } HistoryData data = HistoryData.Empty; int itime = ID.HasValue ? 0 : 1; int ivalue = ID.HasValue ? 1 : 2; int itype = ID.HasValue ? 2 : 3; while (dataReader.Read()) { data.ID = ID.HasValue ? ID.Value : dataReader.GetInt16(0); data.TimeStamp = dataReader.GetDateTime(itime); switch ((DataType)dataReader.GetByte(itype)) { case DataType.BOOL: data.Value.Boolean = dataReader.GetFloat(ivalue) > 0 ? true : false; break; case DataType.BYTE: data.Value.Byte = Convert.ToByte(dataReader.GetFloat(ivalue)); break; case DataType.WORD: case DataType.SHORT: data.Value.Int16 = Convert.ToInt16(dataReader.GetFloat(ivalue)); break; case DataType.INT: data.Value.Int32 = Convert.ToInt32(dataReader.GetFloat(ivalue)); break; case DataType.FLOAT: data.Value.Single = dataReader.GetFloat(ivalue); break; } yield return(data); } } yield break; }
public static int WriteToFile(DateTime date)//每天凌晨写入昨天的数据到文件,可以考虑用服务或计划任务;数据库只保留当天的记录;调度程序负责删除过期记录;历史数据应支持合并 { int year = date.Year; int month = date.Month; int day = date.Day; string path = string.Concat(m_Path, "\\", year.ToString(), "-", month.ToString(), ".bin"); if (CreateFile(year, month))//如该月文件不存在,则创建;否则写入 { using (FileStream stream = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.Read)) { stream.Seek(day * 8, SeekOrigin.Begin); //先读入索引区,定位到该日期的指针 byte[] bits = new byte[8]; stream.Read(bits, 0, 8); //如果该位置指针为>0的正数,说明该区域已有数据 if (BitConverter.ToInt64(bits, 0) > 0) { return(-1); } } using (var dataReader = DataHelper.Instance.ExecuteProcedureReader("WRITEHDATA", DataHelper.CreateParam("@DATE", SqlDbType.DateTime, date))) { if (dataReader == null) { return(-10); } else { dataReader.Read(); int cont = dataReader.GetInt32(0);//读入标签数量 if (cont == 0) { return(-2); } string path2 = path + ".temp"; try { File.Copy(path, path2, true);//先把原文件全部复制到临时文件 //Stopwatch sw = Stopwatch.StartNew(); using (FileStream stream = File.Open(path2, FileMode.Open)) { //w.Seek(8 + day * 8, SeekOrigin.Begin); //w.Seek(0x100, SeekOrigin.Begin); long start = stream.Seek(0, SeekOrigin.End);//定位到文件末尾 long end = 0; using (BinaryWriter w = new BinaryWriter(stream)) { w.Write(new SqlDateTime(date).DayTicks); //写入日期 w.Write(cont); ///写入标签数量 int count = dataReader.GetInt32(1); w.Write(count); HDataFormat[] list = new HDataFormat[count]; if (dataReader.NextResult()) { int p = 0; int x = 0; while (dataReader.Read()) //写入标签元数据 { short id = dataReader.GetInt16(0); //ID号 byte type = dataReader.GetByte(1); //数据类型 int cn = dataReader.GetInt32(2); //标签个数 //list[x].ID = id; list[x].Type = (DataType)type; list[x].Count = cn; //list[x].Offset = p; w.Write(id); w.Write(type); w.Write(cn); w.Write(p); p += cn * dataLen[type]; x++; } if (dataReader.NextResult()) { for (int i = 0; i < list.Length; i++) { int len = list[i].Count; for (int j = 0; j < len; j++) { if (dataReader.Read()) { w.Write(dataReader.GetTimeTick(0)); switch (list[i].Type) { case DataType.BOOL: w.Write(dataReader.GetFloat(1) > 0); break; case DataType.BYTE: w.Write((byte)dataReader.GetFloat(1)); break; case DataType.WORD: case DataType.SHORT: w.Write((short)dataReader.GetFloat(1)); break; case DataType.INT: w.Write((int)dataReader.GetFloat(1)); break; case DataType.FLOAT: w.Write(dataReader.GetFloat(1)); break; } } } } } } end = stream.Position; //文件的结尾,总长度 w.Seek((day - 1) * 8, SeekOrigin.Begin); //定位到索引区 w.Write(start); //写入当日指针 w.Write(end); //写入下一日指针 //w.Close(); } } File.Copy(path2, path, true); } catch (Exception err) { DataHelper.AddErrorLog(err); return(-3); } finally { if (File.Exists(path2)) { File.Delete(path2); } } //dataReader.Close(); return(0); /*写入失败,则将备份文件还原;数据库不做删除动作,保留记录,次日服务检查数据文件是否存在,不存在则合并写入 * 可在服务内建XML文件保存失败记录的日期列表,以便还原;用File.Mov;定时间隔、开始时间也可XML定义。 * 先备份二进制归档库,再加载数据库数据,写入文件;如成功,删除数据库当日记录并删除备份文件 * sw.Stop(); * if (sw.ElapsedTicks > 0) { } */ } } } return(-10); }