using DocumentFormat.OpenXml.Drawing;
using DocumentFormat.OpenXml.Office.Word;
using DocumentFormat.OpenXml.Spreadsheet;
using DocumentFormat.OpenXml.Wordprocessing;
using KssSmaPlaLib.Commons;
using Serilog;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using static KssSmaPlaLib.IO.Database.DbUxer;
using Path = System.IO.Path;
namespace KssSmaPlaLib.IO.Database
{
///
/// DBアクセスアシスタント
///
public class DbUxer : IDisposable
{
public enum DbProvider
{
PostgreSQL,
SQLServer,
MySQL,
Oracle,
SQLite,
}
///
/// プロバイダ名ディクショナリ
///
private static readonly Dictionary _providerNameDic = new Dictionary()
{
{ DbProvider.PostgreSQL, "Npgsql" },
{ DbProvider.SQLServer, "System.Data.SqlClient" },
{ DbProvider.MySQL, "MySql.Data.MySqlClient" },
{ DbProvider.Oracle, "Oracle.ManagedDataAccess.Client" },
{ DbProvider.SQLite, "System.Data.SQLite" },
};
///
/// プロバイダ名(文字列)からenum値に変更
///
/// プロバイダ名(文字列)
/// enum値(該当なし時はnull)
public static DbProvider? GetDbProviderEnumFromString(string dbProviderName = "PostgreSQL")
{
switch(dbProviderName.ToLower().Replace(" ",""))
{
case "postgresql":
case "ポスグレ":
return DbProvider.PostgreSQL;
case "sqlserver":
return DbProvider.SQLServer;
case "mysql":
return DbProvider.MySQL;
case "oracle":
case "oracledatabase":
return DbProvider.Oracle;
case "sqlite":
case "sqlite3":
return DbProvider.SQLite;
default:
return null;
}
}
///
/// コミット済みフラグ
///
private bool _isCommitted = false;
///
/// SQLディクショナリ
///
private static readonly Dictionary _sqlDic = new Dictionary();
///
/// 指定フォルダからSQLファイルを読み込む(ディクショナリ保存)
///
/// フォルダパス
/// 成否
public static bool TryLoadSqlFromText(string folderPath, out string resultMessage)
{
resultMessage = string.Empty;
var fileCount = 0;
List files = new List();
try
{
if (string.IsNullOrEmpty(folderPath))
{
resultMessage = "フォルダパスが指定されていません。";
return false;
}
if (!Directory.Exists(folderPath))
{
resultMessage = $"フォルダが存在しません。[フォルダパス:{folderPath}]";
return false;
}
_sqlDic.Clear();
foreach (var file in Directory.GetFiles(folderPath, "*.sql.txt"))
{
_sqlDic.Add(Path.GetFileNameWithoutExtension(file).ToLower().Replace(".sql", ""), System.IO.File.ReadAllText(file));
files.Add(Path.GetFileNameWithoutExtension(file).Replace(".sql", ""));
fileCount++;
}
resultMessage = $"SQLファイルをロードしました。[ファイル数:{fileCount},ファイル:{string.Join(",", files)}]";
return true;
}
catch (Exception ex)
{
resultMessage = $"SQLファイル読み込み時にエラーが発生しました。[エラー内容:{ex.Message}]";
return false;
}
}
// public static bool TestConnectByDic(Dictionary iniDic, out string resultMessage)
// {
// const string KEY_DB_PROVIDER_NAME = "DbProviderName";
// const string KEY_DB_CONNECTION_STRING = "DbConnectionString";
// var dbProviderName = DictionaryUxer.GetValueOrDefault(iniDic, KEY_DB_PROVIDER_NAME, string.Empty);
// var connectionString = DictionaryUxer.GetValueOrDefault(iniDic, KEY_DB_CONNECTION_STRING, string.Empty);
// return TestConnect(dbProviderName, connectionString, out resultMessage);
// }
///
/// テスト接続
///
/// 成否
// public static bool TestConnect(string dbPrividerName, string dbConnectionString, out string resultMessage)
// {
// // パラメータチェック&DBプロバイダ取得
// if (!TryConnectParameter(dbPrividerName, dbConnectionString, out DbProvider? _, out resultMessage))
// {
// return false;
// }
// if (!TryCreate(dbPrividerName, dbConnectionString, out var dbUxer, out resultMessage, false))
// {
// return false;
// }
// dbUxer.Dispose();
// return true;
// }
///
/// DB接続
///
private DbConnection? _con = null;
///
/// トランザクション
///
private DbTransaction? _tran = null;
// public static bool TryCreateByDic(Dictionary iniDic, out DbUxer dbUxer, out string resultMessage, bool useTransaction = false)
// {
// const string KEY_DB_PROVIDER_NAME = "DbProviderName";
// const string KEY_DB_CONNECTION_STRING = "DbConnectionString";
// var dbProviderName = DictionaryUxer.GetValueOrDefault(iniDic, KEY_DB_PROVIDER_NAME, string.Empty);
// var connectionString = DictionaryUxer.GetValueOrDefault(iniDic, KEY_DB_CONNECTION_STRING, string.Empty);
// return TryCreate(dbProviderName, connectionString, out dbUxer, out resultMessage, useTransaction);
// }
///
/// 生成挑戦
///
///
///
///
///
///
///
// public static bool TryCreate(string dbPrividerName, string dbConnectionString, out DbUxer dbUxer, out string resultMessage, bool useTransaction = false)
// {
// dbUxer = null;
// // パラメータチェック&DBプロバイダ取得
// if (!TryConnectParameter(dbPrividerName, dbConnectionString, out DbProvider? dbp, out resultMessage))
// {
// return false;
// }
// DbProvider dbpp = (DbProvider)dbp;
// try
// {
// // 生成
// dbUxer = new DbUxer(dbpp, dbConnectionString, useTransaction);
// return true;
// }
// catch (Exception ex)
// {
// // 接続NG回答
// resultMessage = $"DB接続に失敗しました。[エラー内容:{ex.Message}]";
// return false;
// }
// }
private static bool TryConnectParameter(string dbPrividerName, string dbConnectionString, out DbProvider? dbp, out string resultMessage)
{
dbp = DbProvider.PostgreSQL;
resultMessage = string.Empty;
if (string.IsNullOrEmpty(dbPrividerName))
{
// DBプロバイダ指定なしの場合、デフォルトはポスグレとする
// Infoメッセージ
resultMessage = "DBプロバイダ名が未指定のため、デフォルトのPostgreSQLを使用します。";
}
if (string.IsNullOrEmpty(dbConnectionString))
{
resultMessage = "接続文字列が設定されていません。";
return false;
}
if (!string.IsNullOrEmpty(dbPrividerName))
{
dbp = GetDbProviderEnumFromString(dbPrividerName);
}
if (dbp == null)
{
resultMessage = $"DBプロバイダ名が不正です。[DBプロバイダ名:{dbPrividerName}]";
return false;
}
return true;
}
///
/// コンストラクタ(DB接続)
///
/// DBプロバイダ(enum値)
/// 接続文字列
/// トランザクション有無
private DbUxer(DbProvider dbProvider, string connectionString, bool useTransaction = false)
{
// try
// {
// // DBプロバイダファクトリー作成
// DbProviderFactory factory;
// if (dbProvider == DbProvider.PostgreSQL)
// {
// // ポスグレの場合、Npgsqlのインスタンをを直接取得
// factory = Npgsql.NpgsqlFactory.Instance;
// }
// else
// {
// factory = DbProviderFactories.GetFactory(_providerNameDic[dbProvider]);
// }
// // DB接続作成
// _con = factory.CreateConnection();
// // 接続文字列設定
// _con.ConnectionString = connectionString;
// // 接続
// _con.Open();
// // トランザクション
// if (useTransaction) _tran = _con.BeginTransaction();
// }
// catch (Exception ex)
// {
// LoggerUxer.Error($"DB接続に失敗しました。[プロバイダ:{dbProvider},接続文字列:{connectionString},エラー内容:{ex.Message}]");
// throw ex;
// }
}
// public bool ExecuteNonQuery(string sqlOrName, Dictionary parameters, out int resultCount, out string resultMessage)
// {
// resultCount = 0;
// resultMessage = string.Empty;
// if (_con == null || _con.State != ConnectionState.Open)
// {
// resultMessage = "DBと接続されていません。";
// return false;
// }
// try
// {
// using (var cmd = _con.CreateCommand())
// {
// // コパンドプロパティを注入
// if (!TryInjectSoulToCmd(cmd, sqlOrName, parameters, out var messageForMe))
// {
// resultMessage = messageForMe;
// return false;
// }
// resultCount = cmd.ExecuteNonQuery();
// LoggerUxer.Info($"[Rec Count:{resultCount}]");
// return true;
// }
// }
// catch (Exception ex)
// {
// resultMessage = $"SQL実行でエラーが発生しました。[SQL名:{sqlOrName},エラー内容:{ex.Message}]";
// return false;
// }
// }
// public bool ExecuteQuery(string sqlOrName, Dictionary parameters, out List> recordSet, out string resultMessage)
// {
// recordSet = new List>();
// resultMessage = string.Empty;
// if (_con == null || _con.State != ConnectionState.Open)
// {
// resultMessage = "DBと接続されていません。";
// return false;
// }
// try
// {
// using (var cmd = _con.CreateCommand())
// {
// // コパンドプロパティを注入
// if (!TryInjectSoulToCmd(cmd, sqlOrName, parameters, out var messageForMe))
// {
// resultMessage = messageForMe;
// return false;
// }
// using (var reader = cmd.ExecuteReader())
// {
// while (reader.Read())
// {
// var row = new Dictionary();
// for (int i = 0; i < reader.FieldCount; i++)
// {
// row[reader.GetName(i)] = reader.GetValue(i);
// }
// recordSet.Add(row);
// }
// LoggerUxer.Info($"[Rec Count:{recordSet.Count}]");
// }
// }
// return true;
// }
// catch (Exception ex)
// {
// resultMessage = $"DBからデータ取得時にエラーが発生しました。[SQL名:{sqlOrName},エラー内容:{ex.Message}]";
// return false;
// }
// }
// private bool TryInjectSoulToCmd(DbCommand cmd, string sqlOrName, Dictionary parameters, out string resultMessage)
// {
// resultMessage = string.Empty;
// // SQLの取得
// sqlOrName = sqlOrName.ToLower();
// var sql = _sqlDic.ContainsKey(sqlOrName) ? _sqlDic[sqlOrName] : sqlOrName;
// //LoggerUxer.Info($"[SQL:{sql}]");
// // SQL中のコマンドパラメータ名取得
// var paraList = ExtractSqlParams(sql);
// //oggerUxer.Info($"[SQL Para names:{string.Join(",", paraList)}]");
// // コマンドパラメータ値の型変換
// if (!TryChangeParamTypeFromSqlParams(ref parameters, ref paraList, out var messageForMe))
// {
// resultMessage = $"コマンドパラメータ値の型変換に失敗しました。[エラー内容:{messageForMe}]";
// return false;
// }
// // SQL文中のコマンドパラメータ型定義をカット
// cmd.CommandText = sql = CutParamTypeOfSQL(sql);
// //LoggerUxer.Info($"[SQL(Param Type Cut):{sql}]");
// // 再度、SQL中のコマンドパラメータ名取得
// paraList = ExtractSqlParams(sql);
// //LoggerUxer.Info($"[SQL Para names(Type cut):{string.Join(",", paraList)}]");
// // SQLに合わせたコマンドパラメータ登録
// foreach (var p in parameters)
// {
// if (!paraList.Contains(p.Key)) continue;
// var param = cmd.CreateParameter();
// param.ParameterName = p.Key;
// param.Value = p.Value;
// cmd.Parameters.Add(param);
// }
// //LoggerUxer.Info($"[SQL Params:{GetCommandParametersCsv(cmd)}]");
// if (cmd.Parameters.Count != paraList.Count)
// {
// resultMessage = $"必要なパラメータが不足しています。[SQL名:{sqlOrName},SQL項目:{string.Join(",", paraList)}, CSV項目:{string.Join(",", parameters.Keys)}]";
// return false;
// }
// return true;
// }
public void Commit()
{
_tran?.Commit();
_isCommitted = true;
}
///
/// 終了処理
///
///
public void Dispose()
{
if (_tran != null && !_isCommitted)
{
Log.Warning("トランザクション未コミット → 自動ロールバックされました");
_tran.Rollback(); // 明示的にロールバック
}
_con?.Dispose();
_con = null;
_tran = null;
}
public static List ExtractSqlParams(string sql)
{
//var matches = System.Text.RegularExpressions.Regex.Matches(sql, @":([a-zA-Z_][a-zA-Z0-9_]*)");
//return matches.Cast()
// .Select(m => m.Groups[1].Value)
// .Distinct()
// .ToList();
//var result = new List();
//var lines = sql.Split(new[] { "\r\n", "\n" }, StringSplitOptions.None);
//foreach (var line in lines)
//{
// // コメント部分を除去
// var codePart = line.Contains("--") ? line.Substring(0, line.IndexOf("--")) : line;
// // パラメータ抽出
// var matches = System.Text.RegularExpressions.Regex.Matches(
// codePart,
// @":(\[[a-zA-Z]\][a-zA-Z_][a-zA-Z0-9_]*)|:([a-zA-Z_][a-zA-Z0-9_]*)"
// );
// foreach (System.Text.RegularExpressions.Match match in matches)
// {
// var paramName = match.Groups[1].Success ? match.Groups[1].Value : match.Groups[2].Value;
// if (!result.Contains(paramName))
// result.Add(paramName);
// }
//}
//return result;
var result = new List();
var lines = sql.Split(new[] { "\r\n", "\n" }, StringSplitOptions.None);
foreach (var line in lines)
{
// コメント部分を除去
var codePart = line.Contains("--") ? line.Substring(0, line.IndexOf("--")) : line;
// パラメータ抽出(::で始まるものは除外)
var matches = System.Text.RegularExpressions.Regex.Matches(
codePart,
@"(?();
// foreach (DbParameter param in command.Parameters)
// {
// string name = param.ParameterName?.TrimStart('@'); // @を除去(任意)
// object value = param.Value;
// string formattedValue;
// if (value == null || value == DBNull.Value)
// {
// formattedValue = "NULL";
// }
// else if (value is string || value is char)
// {
// formattedValue = $"'{value}'"; // シングルクォートで括る
// }
// else if (value is DateTime dt)
// {
// formattedValue = $"'{dt:yyyy-MM-dd HH:mm:ss}'"; // 日付も文字列扱い
// }
// else
// {
// formattedValue = value.ToString();
// }
// list.Add($"{name}={formattedValue}");
// }
// return string.Join(",", list);
// }
// private static bool TryChangeParamTypeFromSqlParams(ref Dictionary parameters, ref List paraNameList, out string resultMessage)
// {
// resultMessage = string.Empty;
// foreach (var key in parameters.Keys.ToList())
// {
// var name = paraNameList
// .FirstOrDefault(m => m == key || m.Substring(0, 1) == "[" && m.Substring(3) == key);
// if (name != null && name.Substring(0, 1) == "[")
// {
// switch (name.Substring(0, 3).ToUpper())
// {
// case "[I]":
// if (string.IsNullOrEmpty(parameters[key].ToString()))
// {
// parameters[key] = DBNull.Value;
// }
// else if (int.TryParse(parameters[key].ToString(), out int intValue))
// {
// parameters[key] = intValue;
// }
// else
// {
// resultMessage = $"パラメータ値[I]型変換に失敗しました。[キー:{key}値:{parameters[key]}]";
// return false;
// }
// break;
// //case "[IN":
// // if (string.IsNullOrEmpty(parameters[key].ToString()))
// // {
// // parameters[key] = DBNull.Value;
// // }
// // else if (int.TryParse(parameters[key].ToString(), out intValue))
// // {
// // parameters[key] = intValue;
// // }
// // else
// // {
// // resultMessage = $"パラメータ値[IN]型変換に失敗しました。[キー:{key}値:{parameters[key]}]";
// // return false;
// // }
// // break;
// case "[F]":
// if (double.TryParse(parameters[key].ToString(), out double doubleValue))
// {
// parameters[key] = doubleValue;
// }
// else
// {
// resultMessage = $"パラメータ値[F]型変換に失敗しました。[キー:{key}値:{parameters[key]}]";
// return false;
// }
// break;
// case "[D]":
// if (DateTime.TryParse(parameters[key].ToString(), out DateTime dtValue))
// {
// parameters[key] = dtValue;
// }
// else
// {
// resultMessage = $"パラメータ値[D]型変換に失敗しました。[キー:{key}値:{parameters[key]}]";
// return false;
// }
// break;
// case "[S]":
// parameters[key] = parameters[key].ToString();
// break;
// }
// }
// }
// return true;
// }
// SQL文中のコマンドパラメータ型定義をカット
private static string CutParamTypeOfSQL(string sql)
{
string[] cutItems = new string[] { "[I]", "[F]", "[D]", "[S]" };
foreach (var cutItem in cutItems)
{
sql = sql.Replace(cutItem.ToUpper(), "");
sql = sql.Replace(cutItem.ToLower(), "");
}
return sql;
}
}
}