using Microsoft.Extensions.Configuration;
|
using Rhea.Common;
|
using SqlSugar;
|
using System;
|
using System.Collections.Generic;
|
using System.Diagnostics;
|
using System.Linq;
|
using System.Text.RegularExpressions;
|
|
namespace Tiger.Business
|
{
|
/// <summary>
|
/// 数据源
|
/// </summary>
|
public class DataSource
|
{
|
/// <summary>
|
/// 数据源
|
/// </summary>
|
/// <param name="config"></param>
|
private DataSource(IConfiguration config)
|
{
|
var dbs = config.AsEnumerable().Where(q => q.Key.StartsWith("Databases:") && q.Value.IsNullOrEmpty());
|
foreach (var item in dbs)
|
{
|
try
|
{
|
Add(new Database()
|
{
|
Name = item.Key.Replace("Databases:", ""),
|
Type = Enum.Parse<DbType>(config[$"{item.Key}:DbType"]),
|
ConnectionString = config[$"{item.Key}:ConnectionString"],
|
});
|
}
|
catch (System.Exception ex)
|
{
|
Logger.Console.Fatal(ex, $"Add Database[{item.Key.Replace("Databases:", "")}] to DataSource Exception");
|
}
|
}
|
}
|
#region 单例
|
private static DataSource _DataSource = null;
|
/// <summary>
|
/// 创建数据源单例
|
/// </summary>
|
/// <param name="_configuration"></param>
|
/// <returns></returns>
|
public static DataSource CreateInstance(IConfiguration _configuration)
|
{
|
if (_DataSource == null)
|
{
|
_DataSource = new DataSource(_configuration);
|
}
|
return _DataSource;
|
}
|
#endregion
|
/// <summary>
|
/// 数据库列表
|
/// </summary>
|
public List<Database> Databases = new List<Database>();
|
/// <summary>
|
/// 按数据库名称获取数据库实例
|
/// </summary>
|
/// <param name="name"></param>
|
/// <returns></returns>
|
public Database this[string name] => Databases.FirstOrDefault(q => q.Name == name);
|
/// <summary>
|
/// 按Index获取数据库实例
|
/// </summary>
|
/// <param name="index"></param>
|
/// <returns></returns>
|
public Database this[int index] => (Databases.Count > index && index >= 0) ? Databases[index] : null;
|
/// <summary>
|
/// 是否存在传入名称的数据库实例
|
/// </summary>
|
/// <param name="name"></param>
|
/// <returns></returns>
|
public bool Exists(string name)
|
{
|
return Databases.Any(q => q.Name == name);
|
}
|
/// <summary>
|
/// 添加数据库到数据源,如果已存在相同名称的数据库则替换
|
/// </summary>
|
/// <param name="database"></param>
|
/// <returns></returns>
|
public DataSource Add(Database database)
|
{
|
Databases.RemoveAll(q => q.Name == database.Name);
|
Databases.Add(database);
|
return this;
|
}
|
/// <summary>
|
/// 按数据库名称从数据源移除数据库
|
/// </summary>
|
/// <param name="name"></param>
|
/// <returns></returns>
|
public DataSource Remove(string name)
|
{
|
Databases.RemoveAll(q => q.Name == name);
|
return this;
|
}
|
}
|
|
/// <summary>
|
/// 数据库
|
/// </summary>
|
public class Database
|
{
|
/// <summary>
|
/// 数据名称
|
/// </summary>
|
public string Name { get; set; }
|
/// <summary>
|
/// 数据库类型
|
/// </summary>
|
public DbType Type { get; set; }
|
/// <summary>
|
/// 连接字符串
|
/// </summary>
|
public string ConnectionString { get; set; }
|
/// <summary>
|
/// 数据库客户端
|
/// </summary>
|
public DbClient Client { get => CreateContext().Db; }
|
/// <summary>
|
/// 数据库基础方法
|
/// </summary>
|
public DbBase Base { get => new DbBase(Client); }
|
/// <summary>
|
/// 创建数据库上下文
|
/// </summary>
|
/// <returns></returns>
|
public DbContext CreateContext()
|
{
|
DbContext context = null;
|
switch (Type)
|
{
|
case DbType.Sqlite:
|
context = new DbContext(ConnectionString.Replace("..\\", AppDomain.CurrentDomain.BaseDirectory), DbType.Sqlite);
|
break;
|
default:
|
context = new DbContext(ConnectionString, Type);
|
break;
|
}
|
return context;
|
}
|
}
|
|
/// <summary>
|
/// 数据库上下文
|
/// </summary>
|
public class DbContext
|
{
|
/// <summary>
|
/// 数据库客户端
|
/// </summary>
|
public DbClient Db;//用来处理事务多表查询和复杂的操作
|
|
/// <summary>
|
/// 构造函数
|
/// </summary>
|
/// <param name="connStr">数据库连接字符串</param>
|
/// <param name="dbType">数据库类型</param>
|
public DbContext(string connStr, DbType dbType)
|
{
|
InitDataBase(connStr, dbType);
|
}
|
|
/// <summary>
|
/// 初始化数据库连接
|
/// </summary>
|
/// <param name="connStr">数据库连接字符串</param>
|
/// <param name="dbType">数据库类型</param>
|
private void InitDataBase(string connStr, DbType dbType)
|
{
|
Db = new DbClient(new ConnectionConfig()
|
{
|
ConnectionString = connStr,
|
DbType = dbType,
|
IsAutoCloseConnection = true,
|
//MoreSettings = new ConnMoreSettings() { DbMinDate = DateTime.MinValue }
|
});
|
Db.Ado.CommandTimeOut = 30000;//设置超时时间
|
Db.Aop.OnLogExecuted = (sql, pars) => //SQL执行完事件
|
{
|
//这里可以查看执行的sql语句跟参数
|
};
|
Db.Aop.OnLogExecuting = (sql, pars) => //SQL执行前事件
|
{
|
//这里可以查看执行的sql语句跟参数 ConsoleExt.WriteLine
|
//Debug.WriteLine($"****************************************** Sql Trace {DateTime.Now.ToString("HH:mm:ss")} ******************************************" +
|
// $"\r\n{sql};{(pars.Length == 0 ? "" : "\r\n--Params:" + Db.Utilities.SerializeObject(pars.ToDictionary(it => it.ParameterName, it => it.Value)))}\r\n");
|
var sqlTrace = $"------------------------------------------ Sql Trace {DateTime.Now.ToString("HH:mm:ss")} ------------------------------------------";
|
var sqlcmd = sql.ToUpper();
|
foreach (var par in pars.OrderByDescending(q => q.ParameterName.Length))
|
{
|
sqlcmd = sqlcmd.Replace(par.ParameterName.ToUpper(), $"'{par.Value}'", StringComparison.CurrentCultureIgnoreCase);
|
}
|
sqlTrace += $"\r\n{sqlcmd.Replace("\r", "").Replace("\n", "")};\r\n-- SQL:{sql.Replace("\r", "").Replace("\n", "")}{(pars.Length == 0 ? "" : "\r\n-- Params:" + Db.Utilities.SerializeObject(pars.ToDictionary(it => it.ParameterName, it => it.Value)))}\r\n";
|
if (!sqlTrace.Contains("LOG_API_ACCESS"))
|
{
|
Debug.WriteLine(sqlTrace);
|
}
|
};
|
Db.Aop.OnError = (exp) =>//执行SQL 错误事件
|
{
|
//这里可以查看执行的sql语句跟参数
|
};
|
Db.Aop.OnExecutingChangeSql = (sql, pars) => //SQL执行前 可以修改SQL
|
{
|
if (pars != null)
|
{
|
foreach (var par in pars)
|
{
|
var dbMinDate = (Db.CurrentConnectionConfig.MoreSettings?.DbMinDate ?? Convert.ToDateTime("1900-01-01"));
|
if (par.DbType == System.Data.DbType.Int16 && (par.Value?.Equals(Int16.MinValue) ?? false))
|
{
|
par.Value = null;
|
}
|
if (par.DbType == System.Data.DbType.Int32 && (par.Value?.Equals(Int32.MinValue) ?? false))
|
{
|
par.Value = null;
|
}
|
if (par.DbType == System.Data.DbType.Int64 && (par.Value?.Equals(Int64.MinValue) ?? false))
|
{
|
par.Value = null;
|
}
|
if (par.DbType == System.Data.DbType.Single && (par.Value?.Equals(Single.MinValue) ?? false))
|
{
|
par.Value = null;
|
}
|
if (par.DbType == System.Data.DbType.Decimal && (par.Value?.Equals(Decimal.MinValue) ?? false))
|
{
|
par.Value = null;
|
}
|
if (par.DbType == System.Data.DbType.Double && (par.Value?.Equals(Double.MinValue) ?? false))
|
{
|
par.Value = null;
|
}
|
if (par.DbType == System.Data.DbType.Date && ((par.Value?.Equals(DateTime.MinValue) ?? false) || (par.Value?.Equals(dbMinDate) ?? false)))
|
{
|
par.Value = null;
|
}
|
if (par.DbType == System.Data.DbType.Time && ((par.Value?.Equals(DateTime.MinValue) ?? false) || (par.Value?.Equals(dbMinDate) ?? false)))
|
{
|
par.Value = null;
|
}
|
if (par.DbType == System.Data.DbType.DateTime && ((par.Value?.Equals(DateTime.MinValue) ?? false) || (par.Value?.Equals(dbMinDate) ?? false)))
|
{
|
par.Value = null;
|
}
|
if (par.DbType == System.Data.DbType.DateTime2 && ((par.Value?.Equals(DateTime.MinValue) ?? false) || (par.Value?.Equals(dbMinDate) ?? false)))
|
{
|
par.Value = null;
|
}
|
}
|
}
|
//适用Oracle:如果等于的值前面带N则去掉
|
if (sql.Contains("=N'"))
|
{
|
sql = sql.Replace("=N'", "='");
|
Debug.WriteLine("适用Oracle:如果等于的值前面带N则去掉,把存在的字符[=N']替换为[=']");
|
}
|
//适用Oracle,Sqlite:如果ID字段在Update语句的Set中则删掉,不更新ID字段的值
|
if ((sql.StartsWith("Begin\r\nUPDATE") || sql.StartsWith("UPDATE")) && Regex.Match(sql, @"(""|`)ID(""|`)[ ]?=[ ]?('([^']*)'|:ID|@ID),", RegexOptions.Multiline).Success)
|
{
|
sql = Regex.Replace(sql, @"(""|`)ID(""|`)[ ]?=[ ]?('([^']*)'|:ID|@ID),", "", RegexOptions.Multiline);
|
Debug.WriteLine("适用Oracle,Sqlite:ID字段在Update语句的Set中则删掉,不需更新ID字段的值,把存在的字符[`ID`=@ID,]替换为空[]");
|
}
|
return new KeyValuePair<string, SugarParameter[]>(sql, pars);
|
};
|
}
|
}
|
}
|