using Aitex.Common.Util; using Aitex.Core.RT.Log; using Aitex.Core.Util; using System; using System.Collections.Generic; using System.Data.Common; using System.Data; using System.IO; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; namespace Aitex.Core.RT.DBCore { public class DataBaseManager : IDataBaseManager { private string _dbName = "sicdb"; private IDataBase _dataBase; private string _sqlFile = PathManager.GetCfgDir() + "DBModel.sql"; private PeriodicJob _monitorJob; private DataBaseCleaner _databaseCleaner = new DataBaseCleaner(); private FixSizeQueue _sqlQueue = new FixSizeQueue(1000); public void Initialize() { DB.Manager = this; _dataBase = new PostgreSQLHelper(_dbName); CreateDataBase(); ExecuteScript(_sqlFile); UpdateTable(); _monitorJob = new PeriodicJob(100, Monitor, "DBJob", true); _databaseCleaner.Initialize(); } /// /// 创建数据库 /// public void CreateDataBase() { try { object obj = _dataBase.ExecuteScalar($"select datname from pg_catalog.pg_database where datname='{_dbName}'"); if (obj == null) { string cmdText = $"CREATE DATABASE {_dbName} WITH OWNER = postgres ENCODING = 'UTF8' TABLESPACE = pg_default CONNECTION LIMIT = -1"; _dataBase.ExecuteNonQuery(cmdText, false); } } catch (Exception ex) { LOG.Error(ex.Message, ex); } } /// /// 执行SQL脚本 /// /// private void ExecuteScript(string sqlFile) { if (string.IsNullOrEmpty(sqlFile) || !File.Exists(sqlFile)) { LOG.Warning("没有更新Sql数据库,文件:" + sqlFile); return; } try { using StreamReader streamReader = new StreamReader(sqlFile); string cmdText = streamReader.ReadToEnd(); _dataBase.ExecuteNonQuery(cmdText); LOG.Info("Database updated by sql file " + sqlFile); } catch (Exception ex) { LOG.Error(ex.Message, ex); } } /// /// 创建Table /// /// /// /// /// public void CreateTable(string tableName, Dictionary columns, bool addPID, string primaryKey) { DbDataReader dataReader = _dataBase.ExecuteReader($"select column_name from information_schema.columns where table_name = '{tableName}'"); if (!dataReader.HasRows) { string sql = addPID ? " \"PID\" serial NOT NULL," : ""; //列名 foreach (KeyValuePair column in columns) { if (column.Value == typeof(int) || column.Value == typeof(ushort) || column.Value == typeof(short)) { sql += $"\"{column.Key}\" integer,"; } else if (column.Value == typeof(double) || column.Value == typeof(float)) { sql += $"\"{column.Key}\" real,"; } else if (column.Value == typeof(string)) { sql += $"\"{column.Key}\" text,"; } else if (column.Value == typeof(DateTime)) { sql += $"\"{column.Key}\" timestamp without time zone,"; } else if (column.Value == typeof(bool)) { sql += $"\"{column.Key}\" boolean,"; } else if (column.Value == typeof(byte[])) { sql += $"\"{column.Key}\" bytea,"; } } //主键 if (string.IsNullOrEmpty(primaryKey)) { if (sql.LastIndexOf(',') == sql.Length - 1) { sql = sql.Remove(sql.Length - 1); } } else { sql += $"CONSTRAINT \"{tableName}_pkey\" PRIMARY KEY (\"{primaryKey}\" )"; } _dataBase.ExecuteNonQuery($"CREATE TABLE \"{tableName}\"({sql})WITH ( OIDS=FALSE );"); } } private void UpdateTable() { //AddTableColumn("carrier_data", new Dictionary //{ // {"rootname",typeof(string) }, // {"recipename",typeof(string)}, // {"filedetail",typeof(byte[]) } //}); //AlterTableColumn("carrier_data", new Dictionary //{ // {"rootname","rootname1" }, // {"recipename","recipename1"}, // {"filedetail","filedetail1" } //}); //DeleteTableColumn("carrier_data", new List //{ // "rootname1", // "recipename1", // "filedetail1" //}); } /// /// 新增Table列名 /// /// /// public void AddTableColumn(string tableName, Dictionary columns) { string sql = $"select column_name from information_schema.columns where table_name = '{tableName}';"; DbDataReader npgsqlDataReader = _dataBase.ExecuteReader(sql); string cmdText = string.Empty; List list = new List(); while (npgsqlDataReader.Read()) { for (int i = 0; i < npgsqlDataReader.FieldCount; i++) { list.Add(npgsqlDataReader[i].ToString()); } } if (list.Count > 0) { foreach (KeyValuePair column in columns) { if (!list.Contains(column.Key)) { cmdText = ((!(column.Value == typeof(bool))) ? ((!(column.Value == typeof(double)) && !(column.Value == typeof(float))) ? ((!(column.Value == typeof(DateTime))) ? ((!(column.Value == typeof(int)) && !(column.Value == typeof(ushort)) && !(column.Value == typeof(short))) ? (cmdText + string.Format("ALTER TABLE \"{0}\" ADD COLUMN \"{1}\" {2};", tableName, column.Key, "text")) : (cmdText + string.Format("ALTER TABLE \"{0}\" ADD COLUMN \"{1}\" {2};", tableName, column.Key, "integer"))) : (cmdText + string.Format("ALTER TABLE \"{0}\" ADD COLUMN \"{1}\" {2};", tableName, column.Key, "timestamp without time zone"))) : (cmdText + string.Format("ALTER TABLE \"{0}\" ADD COLUMN \"{1}\" {2};", tableName, column.Key, "real"))) : (cmdText + string.Format("ALTER TABLE \"{0}\" ADD COLUMN \"{1}\" {2};", tableName, column.Key, "Boolean"))); } } if (!string.IsNullOrEmpty(cmdText)) { _dataBase.ExecuteNonQuery(cmdText); } } } /// /// 更新Table列名 /// /// /// public void AlterTableColumn(string tableName, Dictionary columns) { string sql = $"select column_name from information_schema.columns where table_name = '{tableName}';"; DbDataReader npgsqlDataReader = _dataBase.ExecuteReader(sql); string cmdText = string.Empty; List list = new List(); while (npgsqlDataReader.Read()) { for (int i = 0; i < npgsqlDataReader.FieldCount; i++) { list.Add(npgsqlDataReader[i].ToString()); } } if (list.Count > 0) { foreach (KeyValuePair column in columns) { if (list.Contains(column.Key)) { cmdText += $"ALTER TABLE \"{tableName}\" RENAME COLUMN \"{column.Key}\" TO {column.Value};"; } } if (!string.IsNullOrEmpty(cmdText)) { _dataBase.ExecuteNonQuery(cmdText); } } } public void DeleteTableColumn(string tableName, List columns) { string sql = $"select column_name from information_schema.columns where table_name = '{tableName}';"; DbDataReader npgsqlDataReader = _dataBase.ExecuteReader(sql); string cmdText = string.Empty; List list = new List(); while (npgsqlDataReader.Read()) { for (int i = 0; i < npgsqlDataReader.FieldCount; i++) { list.Add(npgsqlDataReader[i].ToString()); } } if (list.Count > 0) { foreach (string column in columns) { if (list.Contains(column)) { cmdText += $"ALTER TABLE \"{tableName}\" DROP COLUMN \"{column}\";"; } } if (!string.IsNullOrEmpty(cmdText)) { _dataBase.ExecuteNonQuery(cmdText); } } } public void InsertSql(string sql) { _sqlQueue.Enqueue(sql); } public DbDataReader ExecuteReader(string sql) { return _dataBase.ExecuteReader(sql); } public int ExecuteNonQuery(string sql, bool isChangeDB = true) { return _dataBase.ExecuteNonQuery(sql, isChangeDB); } public object ExecuteScalar(string sql) { return _dataBase.ExecuteScalar(sql); } public DataSet ExecuteDataSet(string sql) { return _dataBase.ExecuteDataSet(sql); } public DataTable ExecuteDataTable(string sql) { return _dataBase.ExecuteDataTable(sql); } public bool ExcuteTransAction(List sqlList) { return _dataBase.ExcuteTransAction(sqlList); } private bool Monitor() { try { if (_sqlQueue.Count == 0) { return false; } if (_sqlQueue.TryDequeue(out string sql)) { _dataBase.ExecuteNonQuery(sql); } return true; } catch (Exception ex) { LOG.Error(ex.Message, ex); return false; } } public void Terminate() { _monitorJob?.Stop(); _monitorJob = null; _databaseCleaner?.Terminate(); } /// /// DataTable转成List /// /// /// /// public IList DataTableToList(DataTable dt) where T : new() { IList list = new List(); Type type = typeof(T); foreach (DataRow dr in dt.Rows) { T t = new T(); PropertyInfo[] properties = t.GetType().GetProperties(); foreach (PropertyInfo pi in properties) { if (dt.Columns.Contains(pi.Name)) { if (!pi.CanWrite) { continue; } object value = dr[pi.Name]; if (value != DBNull.Value) { pi.SetValue(t, value, null); } } } list.Add(t); } return list; } /// /// DataTable转成T /// /// /// /// public T DataTableToObject(DataTable dt) where T : new() { T t = new T(); if (dt.Rows == null || dt.Rows.Count == 0) { return t; } DataRow dr = dt.Rows[0]; PropertyInfo[] properties = t.GetType().GetProperties(); foreach (PropertyInfo pi in properties) { if (dt.Columns.Contains(pi.Name)) { if (!pi.CanWrite) { continue; } object value = dr[pi.Name]; if (value != DBNull.Value) { pi.SetValue(t, value, null); } } } return t; } } }