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
{
///
/// 数据源
///
public class DataSource
{
///
/// 数据源
///
///
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(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;
///
/// 创建数据源单例
///
///
///
public static DataSource CreateInstance(IConfiguration _configuration)
{
if (_DataSource == null)
{
_DataSource = new DataSource(_configuration);
}
return _DataSource;
}
#endregion
///
/// 数据库列表
///
public List Databases = new List();
///
/// 按数据库名称获取数据库实例
///
///
///
public Database this[string name] => Databases.FirstOrDefault(q => q.Name == name);
///
/// 按Index获取数据库实例
///
///
///
public Database this[int index] => (Databases.Count > index && index >= 0) ? Databases[index] : null;
///
/// 是否存在传入名称的数据库实例
///
///
///
public bool Exists(string name)
{
return Databases.Any(q => q.Name == name);
}
///
/// 添加数据库到数据源,如果已存在相同名称的数据库则替换
///
///
///
public DataSource Add(Database database)
{
Databases.RemoveAll(q => q.Name == database.Name);
Databases.Add(database);
return this;
}
///
/// 按数据库名称从数据源移除数据库
///
///
///
public DataSource Remove(string name)
{
Databases.RemoveAll(q => q.Name == name);
return this;
}
}
///
/// 数据库
///
public class Database
{
///
/// 数据名称
///
public string Name { get; set; }
///
/// 数据库类型
///
public DbType Type { get; set; }
///
/// 连接字符串
///
public string ConnectionString { get; set; }
///
/// 数据库客户端
///
public DbClient Client { get => CreateContext().Db; }
///
/// 数据库基础方法
///
public DbBase Base { get => new DbBase(Client); }
///
/// 创建数据库上下文
///
///
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;
}
}
///
/// 数据库上下文
///
public class DbContext
{
///
/// 数据库客户端
///
public DbClient Db;//用来处理事务多表查询和复杂的操作
///
/// 构造函数
///
/// 数据库连接字符串
/// 数据库类型
public DbContext(string connStr, DbType dbType)
{
InitDataBase(connStr, dbType);
}
///
/// 初始化数据库连接
///
/// 数据库连接字符串
/// 数据库类型
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(sql, pars);
};
}
}
}