358 lines
18 KiB
C#
358 lines
18 KiB
C#
using KssSmaPlaLib.Batch.Commons;
|
|
using KssSmaPlaLib.Batch.Interface;
|
|
using KssSmaPlaLib.Commons;
|
|
using KssSmaPlaLib.Exchange;
|
|
using KssSmaPlaLib.Ini;
|
|
using KssSmaPlaLib.IO.Database;
|
|
using KssSmaPlaLib.IO.File;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Runtime.InteropServices.ComTypes;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace KssSmaPlaLib.Batch.Exchange
|
|
{
|
|
public class CsvToDbStepHandlerUxer
|
|
{
|
|
public FuncCsvToDbByIniResultDto TryFuncCsvToDbByIni(
|
|
string iniFilePath,
|
|
string sectionName)
|
|
{
|
|
const string KEY_SQL_FOLDER_PATH = "SqlFolderPath";
|
|
const string KEY_CSV_FILE_NAME_PATTERNS = "CsvFileNamePatterns";
|
|
const string KEY_INSERT_SQL_FILES = "InsertSqlFiles";
|
|
const string KEY_DUP_CHECK_SQL_FILES = "DupCheckSqlFiles";
|
|
const string KEY_DELETE_BEFORE_INSERT_SQL_FILES = "DeleteBeforeInsertSqlFiles";
|
|
const string KEY_CSV_ENCODING = "CsvEncoding";
|
|
const string KEY_DB_PROVIDER_NAME = "DbProviderName";
|
|
const string KEY_DB_CONNECTION_STRING = "DbConnectionString";
|
|
const string KEY_CSV_FOLDER_PATH = "CsvFolderPath";
|
|
|
|
var result = new FuncCsvToDbByIniResultDto();
|
|
|
|
var iniDic = IniReferenceResolveUxer.ReadSectionWithReference(iniFilePath, sectionName);
|
|
|
|
// 開始日
|
|
if (!CommonUxer.TryGetStartDate(iniDic, out var startDate, out var messageForMe))
|
|
{
|
|
var msg = $"開始日の取得に失敗しました。[エラー内容:{messageForMe}]";
|
|
LoggerUxer.Error(msg);
|
|
result.Succeeded = false;
|
|
result.ExitCode = (int)RetCodeUxer.RetCode.StartDateError;
|
|
result.ResultMessage = msg;
|
|
return result;
|
|
}
|
|
|
|
// DB接続確認
|
|
if (DbUxer.TestConnectByDic(iniDic, out messageForMe) == false)
|
|
{
|
|
var msg = $"DB接続確認で失敗しました。[エラー内容:{messageForMe}]";
|
|
LoggerUxer.Error(msg);
|
|
result.Succeeded = false;
|
|
result.ExitCode = (int)RetCodeUxer.RetCode.DbConnectError;
|
|
result.ResultMessage = msg;
|
|
return result;
|
|
}
|
|
LoggerUxer.Info($"DB接続確認が成功しました。[プロバイダ名:{DictionaryUxer.GetValueOrDefault(iniDic, KEY_DB_PROVIDER_NAME, string.Empty)},接続文字列:{DictionaryUxer.GetValueOrDefault(iniDic, KEY_DB_CONNECTION_STRING, string.Empty)}]");
|
|
if (!string.IsNullOrEmpty(messageForMe))
|
|
{
|
|
// Infoメッセージがあれば出力
|
|
LoggerUxer.Info(messageForMe);
|
|
}
|
|
|
|
// SQLフォルダパス
|
|
var sqlFolderPath = DictionaryUxer.GetValueOrDefault(iniDic, KEY_SQL_FOLDER_PATH, string.Empty);
|
|
if (string.IsNullOrEmpty(sqlFolderPath))
|
|
{
|
|
var msg = $"設定ファイルにSQLフォルダパスが設定されていません。[キー:{KEY_SQL_FOLDER_PATH}]";
|
|
LoggerUxer.Error(msg);
|
|
result.Succeeded = false;
|
|
result.ExitCode = (int)RetCodeUxer.RetCode.SqlFolderPathNoSetting;
|
|
result.ResultMessage = msg;
|
|
return result;
|
|
}
|
|
|
|
// SQLのロード
|
|
if (!DbUxer.TryLoadSqlFromText(sqlFolderPath, out messageForMe))
|
|
{
|
|
var msg = $"SQLのロードに失敗しました。[フォルダパス:SQL,エラー内容:{messageForMe}";
|
|
LoggerUxer.Error(msg);
|
|
result.Succeeded = false;
|
|
result.ExitCode = (int)RetCodeUxer.RetCode.SqlFileLoadError;
|
|
result.ResultMessage = msg;
|
|
return result;
|
|
}
|
|
LoggerUxer.Info(messageForMe); // 正常メッセージ
|
|
|
|
// CSVファイル名パターン群
|
|
var csvPatterns = DictionaryUxer.GetValueOrDefault(iniDic, KEY_CSV_FILE_NAME_PATTERNS, string.Empty);
|
|
if (string.IsNullOrEmpty(csvPatterns))
|
|
{
|
|
var msg = $"設定ファイルのCSVファイル名パターンが設定されていません。[キー:{KEY_CSV_FILE_NAME_PATTERNS}]";
|
|
LoggerUxer.Error(msg);
|
|
result.Succeeded = false;
|
|
result.ExitCode = (int)RetCodeUxer.RetCode.CsvFileNamePatternsNotSetting;
|
|
result.ResultMessage = msg;
|
|
return result;
|
|
}
|
|
var csvPatternArray = csvPatterns.Split(',');
|
|
|
|
// INSERT文SQLファイル群
|
|
var insertSqlFiles = DictionaryUxer.GetValueOrDefault(iniDic, KEY_INSERT_SQL_FILES, string.Empty);
|
|
var insertSqlFilesArray = insertSqlFiles.Split(',');
|
|
|
|
// 重複チェックSELECT文SQLファイル群
|
|
var dupCheckSqlFiles = DictionaryUxer.GetValueOrDefault(iniDic, KEY_DUP_CHECK_SQL_FILES, string.Empty);
|
|
var dupCheckSqlFilesArray = dupCheckSqlFiles.Split(',');
|
|
|
|
// 挿入前の削除SQLファイル群
|
|
var deleteBeforeInsertSqlFiles = DictionaryUxer.GetValueOrDefault(iniDic, KEY_DELETE_BEFORE_INSERT_SQL_FILES, string.Empty);
|
|
var deleteBeforeInsertSqlFilesArray = deleteBeforeInsertSqlFiles.Split(',');
|
|
|
|
// 要素数チェック
|
|
if (csvPatternArray.Length != insertSqlFilesArray.Length ||
|
|
csvPatternArray.Length != dupCheckSqlFilesArray.Length ||
|
|
csvPatternArray.Length != deleteBeforeInsertSqlFilesArray.Length)
|
|
{
|
|
var msg = $"設定ファイルの要素数が異なります。[{KEY_CSV_FILE_NAME_PATTERNS},{KEY_INSERT_SQL_FILES},{KEY_DUP_CHECK_SQL_FILES},{KEY_DELETE_BEFORE_INSERT_SQL_FILES}]";
|
|
LoggerUxer.Error(msg);
|
|
result.Succeeded = false;
|
|
result.ExitCode = (int)RetCodeUxer.RetCode.IniFileItemCountError;
|
|
result.ResultMessage = msg;
|
|
return result;
|
|
}
|
|
LoggerUxer.Info($"設定ファイルの要素数が一致しています。[要素数:{csvPatternArray.Length},キー:{KEY_CSV_FILE_NAME_PATTERNS},{KEY_INSERT_SQL_FILES},{KEY_DUP_CHECK_SQL_FILES},{KEY_DELETE_BEFORE_INSERT_SQL_FILES}]");
|
|
|
|
var encodingTypeName = DictionaryUxer.GetValueOrDefault(iniDic, KEY_CSV_ENCODING, "utf8");
|
|
var encodingType = EncodingUxer.GetEncodingType(encodingTypeName);
|
|
if (encodingType == null)
|
|
{
|
|
encodingType = EncodingUxer.EncodingType.Utf8WithoutBom;
|
|
LoggerUxer.Warn($"CSVエンコーディングタイプ名が不正です。UFT-8で処理します。[キー:{KEY_CSV_ENCODING},値:{encodingTypeName}]");
|
|
}
|
|
|
|
try
|
|
{
|
|
// DB接続
|
|
if (!DbUxer.TryCreateByDic(iniDic, out DbUxer con, out messageForMe, false/* ★★★ トランザクション有無:true */))
|
|
{
|
|
LoggerUxer.Error(messageForMe);
|
|
result.Succeeded = false;
|
|
result.ExitCode = (int)RetCodeUxer.RetCode.DbConnectError;
|
|
result.ResultMessage = messageForMe;
|
|
return result;
|
|
}
|
|
LoggerUxer.Info($"DBに接続しました。[プロバイダ名:{DictionaryUxer.GetValueOrDefault(iniDic, KEY_DB_PROVIDER_NAME, string.Empty)},接続文字列:{DictionaryUxer.GetValueOrDefault(iniDic, KEY_DB_CONNECTION_STRING, string.Empty)}]");
|
|
|
|
var csvFolderPath = DictionaryUxer.GetValueOrDefault(iniDic, KEY_CSV_FOLDER_PATH, ".");
|
|
LoggerUxer.Info($"[CSVフォルダパス:{csvFolderPath}]");
|
|
|
|
using (con)
|
|
{
|
|
// CSVパターン毎
|
|
for (var cnt = 0; cnt < csvPatternArray.Length; cnt++)
|
|
{
|
|
LoggerUxer.Info($"[CSVパターン{cnt + 1}:{csvPatternArray[cnt]}]");
|
|
|
|
var insertSqlFile = insertSqlFilesArray[cnt];
|
|
var csvFileNamePattern = csvPatternArray[cnt];
|
|
var dupCheckSqlFile = dupCheckSqlFilesArray[cnt];
|
|
var deleteBeforeInsertSqlFile = deleteBeforeInsertSqlFilesArray[cnt];
|
|
|
|
LoggerUxer.Info($"[該当ファイル数:{Directory.GetFiles(csvFolderPath, csvFileNamePattern).Length}]");
|
|
|
|
// ファイル毎
|
|
foreach (var path in Directory.GetFiles(csvFolderPath, csvFileNamePattern))
|
|
{
|
|
if (deleteBeforeInsertSqlFile == "DeleteBeforeInsertWeOrder")
|
|
{
|
|
// 溶接専用!🔥🌊
|
|
|
|
// 最小日の取得(溶接専用ロジック)
|
|
var minDic = new Dictionary<int, DateTime>();
|
|
// CSV読み込み+最小値取得
|
|
if (!GetMinValueByKeyFromCsvFiles<int, DateTime>(path, "line_id", "work_date", ref minDic, out var messageForMe0))
|
|
{
|
|
LoggerUxer.Error(messageForMe0);
|
|
result.Succeeded = false;
|
|
result.ExitCode = (int)RetCodeUxer.RetCode.InsertDbFromCsvFilesError;
|
|
result.ResultMessage = messageForMe;
|
|
return result;
|
|
}
|
|
LoggerUxer.Info($"ライン毎の最小日の取得を完了");
|
|
|
|
if (!string.IsNullOrEmpty(deleteBeforeInsertSqlFile))
|
|
{
|
|
// 挿入前の削除SQLを実行
|
|
LoggerUxer.Info($"挿入前の削除SQLを実行[SQLファイル:{deleteBeforeInsertSqlFile}]");
|
|
|
|
var totalResultCount = 0;
|
|
foreach (var kv in minDic)
|
|
{
|
|
var resultCount = 0;
|
|
if (!con.ExecuteNonQuery(
|
|
deleteBeforeInsertSqlFile,
|
|
new Dictionary<string, object>()
|
|
{
|
|
{ "LINE_ID", kv.Key },
|
|
{ "START_DATE", kv.Value }
|
|
},
|
|
out resultCount,
|
|
out messageForMe))
|
|
{
|
|
var msg = $"挿入前の削除が失敗しました。[エラー内容:{messageForMe}]";
|
|
LoggerUxer.Error(msg);
|
|
result.Succeeded = false;
|
|
result.ExitCode = (int)RetCodeUxer.RetCode.DeleteBeforeInsertException;
|
|
result.ResultMessage = msg;
|
|
return result;
|
|
}
|
|
totalResultCount += resultCount;
|
|
LoggerUxer.Info($"挿入前の削除成功[ラインID:{kv.Key},開始日:{kv.Value},削除件数:{resultCount}]");
|
|
}
|
|
LoggerUxer.Info($"挿入前の削除SQLを完了[更新件数:{totalResultCount}]");
|
|
}
|
|
else
|
|
{
|
|
LoggerUxer.Info($"挿入前の削除処理はSQLが未指定のためスキップしました。[キー:{KEY_DELETE_BEFORE_INSERT_SQL_FILES}]");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!string.IsNullOrEmpty(deleteBeforeInsertSqlFile))
|
|
{
|
|
// 挿入前の削除SQLを実行
|
|
LoggerUxer.Info($"挿入前の削除SQLを実行[SQLファイル:{deleteBeforeInsertSqlFile}]");
|
|
|
|
var totalResultCount = 0;
|
|
if (!con.ExecuteNonQuery(
|
|
deleteBeforeInsertSqlFile,
|
|
new Dictionary<string, object>()
|
|
{
|
|
{ "START_DATE", startDate }
|
|
},
|
|
out var resultCount,
|
|
out messageForMe))
|
|
{
|
|
var msg = $"挿入前の削除が失敗しました。[エラー内容:{messageForMe}]";
|
|
LoggerUxer.Error(msg);
|
|
result.Succeeded = false;
|
|
result.ExitCode = (int)RetCodeUxer.RetCode.DeleteBeforeInsertException;
|
|
result.ResultMessage = msg;
|
|
return result;
|
|
}
|
|
totalResultCount += resultCount;
|
|
LoggerUxer.Info($"挿入前の削除SQLを完了[更新件数:{totalResultCount}]");
|
|
}
|
|
else
|
|
{
|
|
LoggerUxer.Info($"挿入前の削除処理はSQLが未指定のためスキップしました。[キー:{KEY_DELETE_BEFORE_INSERT_SQL_FILES}]");
|
|
}
|
|
}
|
|
|
|
// CSV読み込み+DB挿入
|
|
LoggerUxer.Info($"CSV読み込み+DB挿入を実行[ファイルパス:{path}]");
|
|
if (!CsvDbSyncUxer.InsertDbFromCsvFiles(iniDic, con, path, dupCheckSqlFile, insertSqlFile, out messageForMe, (EncodingUxer.EncodingType)encodingType))
|
|
{
|
|
LoggerUxer.Error(messageForMe);
|
|
result.Succeeded = false;
|
|
result.ExitCode = (int)RetCodeUxer.RetCode.InsertDbFromCsvFilesError;
|
|
result.ResultMessage= messageForMe;
|
|
return result;
|
|
}
|
|
LoggerUxer.Info($"CSV読み込み+DB挿入を完了");
|
|
}
|
|
}
|
|
// コミット
|
|
con.Commit();
|
|
}
|
|
LoggerUxer.Info($"DB処理が完了し、DB接続を終了しました。");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
var msg = $"DB処理にてエラーが発生しました。[エラー内容:{ex.Message}]";
|
|
LoggerUxer.Error(msg);
|
|
result.Succeeded = false;
|
|
result.ExitCode = (int)RetCodeUxer.RetCode.CsvToDbException;
|
|
result.ResultMessage = msg;
|
|
return result;
|
|
}
|
|
result.Succeeded = true;
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// CSVよりキー毎に最小値を取得し辞書で返す
|
|
/// </summary>
|
|
/// <typeparam name="TKeyType"></typeparam>
|
|
/// <typeparam name="TValueType"></typeparam>
|
|
/// <param name="csvFilePath"></param>
|
|
/// <param name="keyColName"></param>
|
|
/// <param name="valueColName"></param>
|
|
/// <param name="minDic"></param>
|
|
/// <param name="resultMessage"></param>
|
|
/// <param name="encodingType"></param>
|
|
/// <returns></returns>
|
|
public static bool GetMinValueByKeyFromCsvFiles<TKeyType, TValueType>(
|
|
string csvFilePath,
|
|
string keyColName,
|
|
string valueColName,
|
|
ref Dictionary<TKeyType, TValueType> minDic,
|
|
out string resultMessage,
|
|
EncodingUxer.EncodingType encodingType = EncodingUxer.EncodingType.Utf8WithoutBom)
|
|
where TKeyType : IComparable<TKeyType>
|
|
where TValueType : IComparable<TValueType>
|
|
{
|
|
// 👇参照型(追記とする)ゆえやめた
|
|
//minDic = new Dictionary<TKeyType, TValueType>();
|
|
resultMessage = string.Empty;
|
|
|
|
try
|
|
{
|
|
// CSV読み込み
|
|
if (!CsvUxer.ImportFromCsv(csvFilePath, out var rs, out var messageForMe, encodingType))
|
|
{
|
|
resultMessage = messageForMe;
|
|
return false;
|
|
}
|
|
|
|
//LoggerUxer.Info($"[CSV件数:{rs.Count}]");
|
|
|
|
foreach (var rec in rs)
|
|
{
|
|
TKeyType key;
|
|
TValueType val;
|
|
try { key = (TKeyType)Convert.ChangeType(rec[keyColName], typeof(TKeyType)); }
|
|
catch (Exception) { continue; };
|
|
try { val = (TValueType)Convert.ChangeType(rec[valueColName], typeof(TValueType)); }
|
|
catch (Exception) { continue; }
|
|
|
|
if (minDic.ContainsKey(key))
|
|
{
|
|
minDic[key] = Comparer<TValueType>.Default.Compare(val, minDic[key]) < 0 ? val : minDic[key];
|
|
}
|
|
else
|
|
{
|
|
minDic[key] = val;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
resultMessage = $"最小日時取得時にエラーが発生しました。[エラー内容:{ex.Message}]";
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
public class FuncCsvToDbByIniResultDto : IFuncResultDto
|
|
{
|
|
public bool Succeeded { get; set; } = false;
|
|
public int ExitCode { get; set; } = 0;
|
|
public string ResultMessage { get; set; } = string.Empty;
|
|
}
|
|
}
|