using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Collections;
using System.Data;
using System.Data.SqlClient;
using Common;
using System.Threading; namespace JSONToDB
{
class Program
{
static object lockObj = new object();
static Settings1 sObj = new Settings1();
static DBHelper mydb = new DBHelper(sObj.Connection.ToString());
static dbhelpers dbhelpers = new dbhelpers(); //读取N个月内的数据
static int GetDateInMonth = sObj.GetDateInMonth;
static void Main(string[] args)
{
/*
1、找到对应目录的文件,
2、解析json存到数据库
*/ Json2db();
// Console.WriteLine("任意键退出!");
// Console.ReadKey(); } #region 读取某个目录的文件解析json插入数据库
/// <summary>
/// 读取某个目录的文件解析json插入数据库
/// </summary>
static protected void Json2db()
{
Console.WriteLine("========【程序已启动,正在运行】========"); string FilePath = sObj.FilePath;
string FileType = "." + sObj.FileType;
string FileRule = sObj.FileRule; //一、读取文件夹下待处理复合规则:SynOrder_20170101.txt的文件!
//①、将文件夹下文件读取到列表中
//--时间过滤规则集合
List<string> listDataTimeRules = new List<string>();
//--符合规则的待导入文件路径集合
List<string> ListFilepaths = new List<string>();
//--状态"在处理中或已经处理的"的待导入文件路径集合
List<string> ListSuccessFilepaths = new List<string>();
//--状态"在处理中或已经处理的"的待导入文件路径集合
List<string> ListFailFilepaths = new List<string>();
//--记录导入失败记录次数
//int FailCunt = 0;
for (int i = ; i < GetDateInMonth; i++)
{
DateTime currentDateTime = DateTime.Now.AddMonths(-i);
listDataTimeRules.Add(FileRule + currentDateTime.Year.ToString() + ((int.Parse(currentDateTime.Month.ToString())) < ? "" + currentDateTime.Month.ToString() : currentDateTime.Month.ToString()));//命名规则添加到集合
}
for (int r = ; r < listDataTimeRules.Count; r++)
{
foreach (string path in (IEnumerable)Directory.GetFiles(FilePath, listDataTimeRules[r] + "??" + FileType, SearchOption.TopDirectoryOnly))//循环读取文件夹下的带插入文档
{
ListFilepaths.Add(path);//添加到待发送结果集合
}
} int filepathsCount = ListFilepaths.Count;
if (filepathsCount > )
{
#region lock
lock (lockObj)
{
#region 目录下有文件时执行
//②、将待处理文件导入日志插入到数据库(过滤重复读取的)
foreach (string inserttingFile in ListFilepaths)
{
string fileName = inserttingFile.Trim().Substring(inserttingFile.LastIndexOf('\\') + , inserttingFile.Length - inserttingFile.LastIndexOf('\\') - );
string[] OptimeArr = inserttingFile.Split('_');
string temp = OptimeArr[OptimeArr.Length - ].ToString();//SynOrder
//将文件名格式为:20160718转化成时间格式
string optime = DateTime.ParseExact(temp.Substring(, temp.Length - ), "yyyyMMdd", new System.Globalization.CultureInfo("zh-CN", true)).ToString();
//开始插入数据库
string nowStatus = GetFileStatus(optime, fileName);
if (nowStatus == "NULL")//为空则添加新导入日志记录
{
InsertFileLog(optime, fileName, inserttingFile, "读取中", "读取中");
//符合条件的新待查到如文件(之前未处理的)
ListSuccessFilepaths.Add(inserttingFile);
}
//以下为遗留处理失败的导入文件
else if (nowStatus == "导入成功" || nowStatus == "导入中")
{
//记录已经处理的文件
ListFailFilepaths.Add(inserttingFile);
}
else//“读取中”和“导入失败” 及其他
{
ListSuccessFilepaths.Add(inserttingFile);
}
}
//过滤后是否还有待导入的文件
if (ListSuccessFilepaths.Count > )
{
// 当前文件序号
int no = ;
int failno = ;
int successno = ;
if (ListFailFilepaths.Count > )
{
Console.WriteLine("已处理文件不需再次处理:");
foreach (string failitem in ListFailFilepaths)
{
++failno;
Console.WriteLine(failno + "、" + failitem.Substring(failitem.LastIndexOf('\\') + , failitem.Length - failitem.LastIndexOf('\\') - ));
}
} Console.WriteLine("检察到新待导入文件共:" + ListSuccessFilepaths.Count + "个:");
foreach (string failitem in ListSuccessFilepaths)
{
++successno;
Console.WriteLine(successno + "、" + failitem.Substring(failitem.LastIndexOf('\\') + , failitem.Length - failitem.LastIndexOf('\\') - ));
}
//二、导入到数据库!开始处理数据
Console.WriteLine("开始处理文件!");
foreach (string inserttingFile in ListSuccessFilepaths)
{
++no;
string fileName = inserttingFile.Trim().Substring(inserttingFile.LastIndexOf('\\') + , inserttingFile.Length - inserttingFile.LastIndexOf('\\') - );
string[] OptimeArr = inserttingFile.Split('_');
string temp = OptimeArr[OptimeArr.Length - ].ToString();//SynOrder
//将中文20160718格式转化成时间格式
string optime = DateTime.ParseExact(temp.Substring(, temp.Length - ), "yyyyMMdd", new System.Globalization.CultureInfo("zh-CN", true)).ToString();
//处理方法++++++++++++
ReadingFileToDB(optime, fileName, inserttingFile.Trim(), no);
}
}
else
{
Console.WriteLine("未检察到新待导入文件,已处理文件不需再次处理:");
foreach (string failitem in ListFailFilepaths)
{
Console.WriteLine(failitem.Substring(failitem.LastIndexOf('\\') + , failitem.Length - failitem.LastIndexOf('\\') - ));
}
} #endregion
//}
#endregion
}
#endregion
}
if (filepathsCount == )
{
Console.WriteLine("当前配置的“" + FilePath + "”目录下,未找到符合规则:“" + FileRule + "" + FileType + "”格式文件。");
Thread.Sleep( * );
}
//Console.WriteLine("========【操作已结束,正在退出】========");
Console.WriteLine("========【本轮操作已结束,检察导入文件夹下是否有更新待导入文件】========");
Thread.Sleep( * );
//Console.ReadKey();
} /// <summary>
/// 读取并处理文件
/// </summary>
/// <param name="optime">时间戳</param>
/// <param name="fileName">当前文件的名称</param>
/// <param name="curPath">当前文件的路径</param>
/// <param name="no">当前目录集合的index</param>
private static void ReadingFileToDB(string optime, string fileName, string curPath, int no)
{
// 当前行
String line;
//二级数据列数最大值
int MaxInsertItem = sObj.MaxCount;//服务个数最大值
string Status = "导入失败";
string Remark = "";
string tempid = string.Empty;
StreamReader srHeader = new StreamReader(curPath, Encoding.UTF8);
using (DataTable dt = new DataTable())
{
try
{
if (UpdateFileLogStatus(optime, fileName, "导入中", Remark))
{
Console.WriteLine(no + "、" + fileName + "文件解析中...");
}
#region 1、遍历第一行 取出表列头
// 1、遍历第一行 取出表列头
while ((line = srHeader.ReadLine()) != null && line.ToString().Length != )
{
dt.Columns.Add("OPTime");
JObject objHeader = (JObject)JsonConvert.DeserializeObject(line);
foreach (KeyValuePair<string, JToken> item in objHeader)
{
Newtonsoft.Json.Linq.JArray nj;
if (item.Value.GetType().ToString() == "Newtonsoft.Json.Linq.JArray")
{
nj = (Newtonsoft.Json.Linq.JArray)item.Value;
int njCount = nj.Count;
//处理复合数据的二级表列头
#region 处理复合数据的二级表列头 最大值:MaxInsertItem
if (item.Key == "orderServices")
{
for (int iii = ; iii < MaxInsertItem; iii++)
{
dt.Columns.Add(item.Key + "_acceptanceTime" + iii);
dt.Columns.Add(item.Key + "_bossRecDate" + iii);
dt.Columns.Add(item.Key + "_serviceCode" + iii);
dt.Columns.Add(item.Key + "_serviceName" + iii);
dt.Columns.Add(item.Key + "_serviceWayToHandle" + iii);
dt.Columns.Add(item.Key + "_operatorAccount" + iii);
dt.Columns.Add(item.Key + "_status" + iii);
dt.Columns.Add(item.Key + "_bossOrderNo" + iii);
dt.Columns.Add(item.Key + "_orderServiceResCode" + iii);
dt.Columns.Add(item.Key + "_orderServiceResName" + iii);
dt.Columns.Add(item.Key + "_resItem" + iii);
dt.Columns.Add(item.Key + "_bizNumber" + iii);
}
}
if (item.Key == "orderAttributes")
{
for (int iii = ; iii < MaxInsertItem; iii++)
{
dt.Columns.Add(item.Key + "_attributeValue" + iii);
dt.Columns.Add(item.Key + "_attributeName" + iii);
}
}
#endregion }
else
{
// 二级子节点为单个值添加以及表头
dt.Columns.Add(item.Key);
}
}
if (dt.Columns.Count > )
{
srHeader.Close();
srHeader.Dispose();
break;
}
}
#endregion
#region 2、解析json数据加载到dt当中
//定义一个解析json数据源开始时间
DateTime Analysis_StartTime = DateTime.Now;
// 2、解析json数据加载到dt当中
using (StreamReader sr = new StreamReader(curPath, Encoding.UTF8))
{
while ((line = sr.ReadLine()) != null && line.ToString().Length != )
{
int j = ;
j++;
DataRow dr = dt.NewRow();
dr["OPTime"] = optime;
JObject objBody = (JObject)JsonConvert.DeserializeObject(line);
foreach (KeyValuePair<string, JToken> item in objBody)
{
Newtonsoft.Json.Linq.JArray nj;
if (item.Value.GetType().ToString() == "Newtonsoft.Json.Linq.JArray")
{
#region 复合节点处理
//复合节点
nj = (Newtonsoft.Json.Linq.JArray)item.Value;
int njCount = nj.Count;
if (njCount > )//是否有二级数据
{
if (njCount >= MaxInsertItem)
{
njCount = MaxInsertItem;
}
//二级节点数据少于最大值,数据用Null补齐数据
else
{
if (item.Key == "orderServices")
{
for (int iii = ; iii < MaxInsertItem - njCount; iii++)
{
dr[item.Key + "_acceptanceTime" + (njCount + iii)] = null;
dr[item.Key + "_bossRecDate" + (njCount + iii)] = null;
dr[item.Key + "_serviceCode" + (njCount + iii)] = null;
dr[item.Key + "_serviceName" + (njCount + iii)] = null;
dr[item.Key + "_serviceWayToHandle" + (njCount + iii)] = null;
dr[item.Key + "_operatorAccount" + (njCount + iii)] = null;
dr[item.Key + "_status" + (njCount + iii)] = null;
dr[item.Key + "_bossOrderNo" + (njCount + iii)] = null;
dr[item.Key + "_orderServiceResCode" + (njCount + iii)] = null;
dr[item.Key + "_orderServiceResName" + (njCount + iii)] = null;
dr[item.Key + "_resItem" + (njCount + iii)] = null;
dr[item.Key + "_bizNumber" + (njCount + iii)] = null;
}
}
if (item.Key == "orderAttributes")
{
for (int iii = ; iii < MaxInsertItem - njCount; iii++)
{
dr[item.Key + "_attributeValue" + (njCount + iii)] = null;
dr[item.Key + "_attributeName" + (njCount + iii)] = null;
}
}
}
//将数据添加到内存datetable
for (int ii = ; ii < njCount; ii++)
{
//当子节点仍然为json对象时候
JObject objBody2 = (JObject)JsonConvert.DeserializeObject(nj[ii].ToString());
foreach (KeyValuePair<string, JToken> item2 in objBody2)
{
string tempItem2value = item2.Value.ToString().TrimStart('"').TrimEnd('"');
if (item2.Key == "acceptanceTime" && tempItem2value.IndexOf('.') > -)
{
//特殊处理1-1、特殊处理字段acceptanceTime 时间格式不正确
tempItem2value = tempItem2value.Substring(, tempItem2value.IndexOf('.')).Trim();
}
if (item2.Key == "acceptanceTime" && tempItem2value.ToString().Length == )
{
//特殊处理1-2、特殊处理字段acceptanceTime 有些为空字符
tempItem2value = null;
}
if (item2.Key == "bossRecDate" && tempItem2value.ToString().Length == || item2.Key == "bossRecDate" && tempItem2value.ToString() == "null")
{
//特殊处理2、字段bossRecDate 有些为空字符
tempItem2value = null;
}
dr[item.Key + "_" + item2.Key + ii] = tempItem2value;
}
}
} #region 为空时特殊处理orderAttributes这个字段有些时候是null
// 5、为空时特殊处理orderAttributes这个字段有些时候是null
else if (item.Key == "orderAttributes")
{
for (int ii = ; ii < MaxInsertItem; ii++)
{
dr[item.Key + "_attributeValue" + ii] = null;
dr[item.Key + "_attributeName" + ii] = null;
}
}
else if (item.Key == "orderServices")
{
for (int ii = ; ii < MaxInsertItem; ii++)
{
dr[item.Key + "_acceptanceTime" + ii] = null;
dr[item.Key + "_bossRecDate" + ii] = null;
dr[item.Key + "_serviceCode" + ii] = null;
dr[item.Key + "_serviceName" + ii] = null;
dr[item.Key + "_serviceWayToHandle" + ii] = null;
dr[item.Key + "_operatorAccount" + ii] = null;
dr[item.Key + "_status" + ii] = null;
dr[item.Key + "_bossOrderNo" + ii] = null;
dr[item.Key + "_orderServiceResCode" + ii] = null;
dr[item.Key + "_orderServiceResName" + ii] = null;
dr[item.Key + "_resItem" + ii] = null;
dr[item.Key + "_bizNumber" + ii] = null;
}
}
#endregion
#endregion
}
else
{
// 单节点处理
#region 单节点处理
string tempItemValue = item.Value.ToString().TrimStart('"').TrimEnd('"').Trim();
if (item.Key == "orderTime" && tempItemValue.Length == )
{
//特殊处理3、字段orderTime 有些为空字符
tempItemValue = null;
}
if (item.Key == "orderCompleteTime" && tempItemValue.Length == )
{
//特殊处理4、字段orderCompleteTime 有些为空字符
tempItemValue = null;
}
dr[item.Key] = tempItemValue;
#endregion
// debug 提取错误定位
//if (item.Key == "orderPhone")
//{
// tempid = item.Value.ToString();
//}
}
}
dt.Rows.Add(dr);
//Console.WriteLine("执行到:" + j + " 时间:" + dr["orderServices_acceptanceTime"].ToString() + "|" + dr["orderServices_bossRecDate"]);
}
Console.WriteLine(no + "、" + fileName + "解析完毕!"); // 解析json文件耗时
TimeSpan Analysis_ts = DateTime.Now - Analysis_StartTime;
Console.WriteLine(no + "、" + fileName + "文件,数据共:" + dt.Rows.Count + "条,解析完成,耗时:" + Analysis_ts + " ,开始执行数据插入操作..."); Console.WriteLine("文件导入中..."); // 实例化一个SqlBulkCopy对象
SqlBulkCopy bulkCopy = new SqlBulkCopy(sObj.Connection);
// 设置超时时间
bulkCopy.BulkCopyTimeout = ;
bulkCopy.BatchSize = dt.Rows.Count;
// 指定表名
bulkCopy.DestinationTableName = "Mid_SynOrder";
// 将table和数据库表的字段名对应
for (int k = ; k < dt.Columns.Count; k++)
{
bulkCopy.ColumnMappings.Add(dt.Columns[k].ToString(), dt.Columns[k].ToString());
}
//定义一个执行sql开始时间
DateTime Query_StartTime = DateTime.Now;
// 执行写入操作
bulkCopy.WriteToServer(dt);
// 执行sql批量插入耗时
TimeSpan Query_ts = DateTime.Now - Query_StartTime;
Console.WriteLine(no + "、" + fileName + "文件数据共:" + dt.Rows.Count + " 条,插入完成,共耗时:" + Query_ts + "。");
Remark = "未出现异常,当前数据已成功插入数据库" + "完成当前时间" + DateTime.Now.ToLocalTime();
if (UpdateFileLogStatus(optime, fileName, "导入成功", Remark))
{
Console.WriteLine(no + "、" + fileName + "导入成功!");
}
}
#endregion
}
catch (Exception e)
{
string Error = e.Message.ToString();
Status = "导入失败";
Remark = "出现异常,异常详情:" + Error + "当前时间" + DateTime.Now.ToLocalTime();
Console.WriteLine("异常:" + Error + "orderphone" + tempid);//+ "orderphone" + tempid
if (UpdateFileLogStatus(optime, fileName, Status, Remark))
{
Console.WriteLine("文件导入导入失败!!!");
}
}
}
} #region 获取带处理的文件的状态 /// <summary>
/// 获取带处理的文件的状态
/// </summary>
/// <param name="optime"></param>
/// <returns></returns>
static protected string GetFileStatus(string OPTime, string FileName)
{
string FileStatus = string.Empty;
if (OPTime != "" && FileName != "")
{
string SqlStr = " SELECT status FROM dbo.Mid_SynOrder_Log WHERE OPTime='" + OPTime + "' and FileName='" + FileName + "'"; DataTable dt = mydb.RunTable(SqlStr);
if (dt.Rows.Count > )
{
FileStatus = dt.Rows[]["status"].ToString();
}
else
{
FileStatus = "NULL";
}
}
return FileStatus;
}
#endregion #region 插入导入文件的记录
/// <summary>
/// 插入导入文件的记录
/// </summary>
/// <param name="OPTime"></param>
/// <param name="FileName"></param>
/// <param name="FilePath"></param>
/// <param name="Status"></param>
/// <param name="Remark"></param>
/// <returns></returns>
static protected bool InsertFileLog(string OPTime, string FileName, string FilePath, string Status, string Remark)
{
string sqlStr = " INSERT INTO dbo.Mid_SynOrder_Log(OPTime, FileName, FilePath, Status, Remark) VALUES ('" + OPTime + "','" + FileName + "','" + FilePath + "','" + Status + "','" + Remark + "') ";
bool b = dbhelpers.OperaBoolDB(sqlStr);
return b;
}
#endregion #region 修改导入文件的记录的状态
/// <summary>
/// 修改导入文件的记录的状态
/// </summary>
/// <param name="OPTime"></param>
/// <param name="FileName"></param>
/// <param name="Status"></param>
/// <returns></returns>
static protected bool UpdateFileLogStatus(string OPTime, string FileName, string Status)
{
string sqlStr = " update dbo.Mid_SynOrder_Log set Status ='" + Status + "' where OPTime='" + OPTime + "' and FileName='" + FileName + "' ";
bool b = dbhelpers.OperaBoolDB(sqlStr);
return b;
}
/// <summary>
/// 更新状态并添加备注信息
/// </summary>
/// <param name="OPTime"></param>
/// <param name="FileName"></param>
/// <param name="Status"></param>
/// <param name="Remark"></param>
/// <returns></returns>
static protected bool UpdateFileLogStatus(string OPTime, string FileName, string Status, string Remark)
{
string sqlStr = " update dbo.Mid_SynOrder_Log set Status ='" + Status + "',Remark ='" + Remark + "' where OPTime='" + OPTime + "' and FileName='" + FileName + "' ";
bool b = dbhelpers.OperaBoolDB(sqlStr);
return b;
}
#endregion }
}