配置
1、配置的功能
此处配置的核心用处,在于将不同系统的数据库定义方式与核心逻辑分开,由具体业务系统定义基于xml或者json等配置读入数据库连接的配置,创建数据库实例。
2、数据库连接的配置
核心库 提供的配置相关类
DBInsCash ---- 数据库实例缓存类。
DBInstance ---- 数据库实例类
SQLBuilder ---- SQL编织器类
BulkBase ---- BulkInsert批量插入的操作类
3、多端一致性的惯性定义子类。
DBCash --- 持有工厂类,定义数据配置的读取方式,生产可供直接使用的 SQLBuilder/BatchSQL等实例。
99
配置案例-UCML
0、各类数据库配置示例:
SQLServer 数据库: MSSQL
xml
Enlist=false;Data Source=137.12.*.*;Database=**;User Id=***;Password=***;Encrypt=True;TrustServerCertificate=True;OceanBase数据库: OceanBase
xml
server=137.12.7.*;database=****;user Id=xxxx@xxx#xx;password=xxxxxxxx;pooling=true;Port=8088;Charset=utf8mb4;Convert Zero Datetime=True;MySQL数据库: MySQL
xml
server=10.16.10.*;database=xxx;user Id=xxxx;password=xxxxx;pooling=true;Port=3306;Charset=utf8mb4;Convert Zero Datetime=True;Postgre数据库 PostgreSQL
xml
PORT=5432;DATABASE=xxx;HOST=137.12.7.**;PASSWORD=xxxxxxxxxx;USER ID=xxxxx;独立配置
现在mooSQL已支持独立的数据库配置,以便快速进行数据库配置(自2024.11版本开始)。配置核心项为 Connections数组,具体属性含义如下:
json
"Connections": [
{ // 数据库1 --
"Position": 1,//索引编码,整型,在DBCash中被使用
"Name": "UcmlTar",//字符型名称
"DbType": "MSSQL", // MSSQL/Oracle/Access/PostgreSQL/MySQL/OceanBase/Taos/GBase8a
"ConnectString": "server=*.*.*.*;database=*;user Id=**;password=**;pooling=true;Port=3306;Charset=utf8mb4;Convert Zero Datetime=True;", // 库连接字符串
"Version": "13.0.0",// 数据库版本号
"VersionNumber":13.0 //数值型版本号
},
{ // 数据库2 --
"Position": 2,
"Name": "Device",
"DbType": "MySQL", //
"ConnectString": "server=*.*.*.*;database=*;user Id=**;password=**;pooling=true;Port=3306;Charset=utf8mb4;Convert Zero Datetime=True;", // 库连接字符串
"Version": "5.7.21"
}DBCash
c#
public partial class DBCash
{
private static DBInsCash cash = null;
public static DBInstance GetDBInstance(int position) {
if (cash == null) {
createCash();
}
return cash.getInstance(position);
}
private static void createCash() {
cash = new DBInsCash();
MooEventHandler handler = new MooEventHandler();
string str = getCurPath();
var tar = (str + "/bin/ucmlconf.xml");
cash.configPath = tar;
cash.client.events.onBuildSetFrag((SetFrag frag, SQLBuilder builder)=>
{
var pair = frag.values[builder.InsertRowIndex];
if (pair.paramed)
{
var val = pair.value;
if (val is JValue)
{
pair.value = val.ToString();
}
}
return true;
});
cash.client.events.onBuildWhereFrag((WhereFrag frag, SQLBuilder builder)=>
{
if (frag.paramed)
{
var val = frag.value;
if (val is JValue)
{
frag.value = val.ToString();
}
}
return true;
});
}
private static string getCurPath()
{
if (UCMLCommon.UCMLInitEnv.Server != null) {
return UCMLCommon.UCMLInitEnv.Server.MapPath("~");
}
var cur= Assembly.GetExecutingAssembly().Location;
var i=cur.LastIndexOf('\\');
var path=cur.Substring(0,i);
return path;
}
public static SQLKit newKit(int position)
{
var db= GetDBInstance(position);
var kit = new SQLKit();
kit.setDBInstance(db);
return kit;
}
public static BulkTable newBulk(string tableName, int position) {
BulkTable bk= new BulkTable(tableName,GetDBInstance(position));
bk.getBulkTable();
return bk;
}
public static BatchSQL newBatchSQL(int position)
{
var db = GetDBInstance(position);
var kit = new SQLKit();
kit.setDBInstance(db);
var res = new BatchSQL(kit);
return res;
}
}日志输出
方式1 重写监听器类
c#
public class QueryWatchor : Watchor {
public override string onAfterExecuteSetError(string oprationId, ExeContext context, Exception ex, string operation)
{
var sql = context.cmd.cmdText;
var paras = context.cmd.para;
var msg = "";
foreach (var para in paras.value)
{
sql = sql.Replace(para.Key, para.Value.val.ToString());
msg += string.Format("参数{0}:{1},", para.Key, para.Value.val);
}
var info = string.Format("SQL执行期间发生错误({1}):{2}\nSQL:{0},\n", sql, DateTime.Now.ToString(),ex.Message);
saveFileLog(info);
return info;
}
private void saveFileLog(string message)
{
//未能找到路径“D:\PXXT\getHRManSql.txt”的一部分。
string str = UCMLCommon.UCMLInitEnv.Server.MapPath("~");
var tar = (str + "/log/moosql/");
var filepath = tar;
//子路径不存在时创建
System.IO.DirectoryInfo dir = new DirectoryInfo(filepath);
if (!dir.Exists)
{
dir.Create();
}
//名称格式 年月日 时分秒 随机码
var dand = new Random();
var fileName = string.Format("errSql{0}_{1}_{2}.txt", DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day);
File.AppendAllText(filepath+fileName, message);
}
} 然后重写工厂类,然后在DBCash中调用
c#
public class DBInsFactory:DBInsCash {
public DBInsFactory()
{
}
public override IExeLog getExeQueryLog()
{
return new QueryLog();
}
public override IWatchor getExeWatchor()
{
return new QueryWatchor();
}
}参数格式转换
c#
public class MooEventHandler {
public bool onCheckSetVal(SetFrag frag, SQLBuilder builder)
{
var pair = frag.values[builder.InsertRowIndex];
if (pair.paramed)
{
var val = pair.value;
if (val is JValue)
{
pair.value = val.ToString();
}
}
return true;
}
public bool onCheckWhereVal(WhereFrag frag, SQLBuilder builder)
{
if (frag.paramed)
{
var val = frag.value;
if (val is JValue)
{
frag.value = val.ToString();
}
}
return true;
}
}关于调试
1、打断点
SQLBuilder 的 do...系列方法,内部都会调用 to...系列方法来创建SQL。 因此,可以在 to方法中打断点来查看SQL。
2、事件。
DBCash中,提供多个SQL执行生命期的事件,可以在事件注册方法中打断点。同样可以查询SQL。
3、异常
注册异常事件。一般会在DBCash中注册异常事件,并输出SQL错误的日志,便于后续核查。