445 lines
15 KiB
C#
445 lines
15 KiB
C#
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;
|
||
using Npgsql;
|
||
|
||
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<string> _sqlQueue = new FixSizeQueue<string>(1000);
|
||
|
||
public void Initialize()
|
||
{
|
||
DB.Manager = this;
|
||
|
||
_dataBase = new PostgreSQLHelper(_dbName);
|
||
|
||
CreateDataBase();
|
||
|
||
ExecuteScript(_sqlFile);
|
||
|
||
UpdateTable();
|
||
|
||
_monitorJob = new PeriodicJob(100, Monitor,"DataBaseManager", true);
|
||
|
||
_databaseCleaner.Initialize();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 创建数据库
|
||
/// </summary>
|
||
public void CreateDataBase()
|
||
{
|
||
try
|
||
{
|
||
object obj = _dataBase.ExecuteScalar($"select datname from pg_catalog.pg_database where datname='{_dbName}'", false);
|
||
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);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 执行SQL脚本
|
||
/// </summary>
|
||
/// <param name="sqlFile"></param>
|
||
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);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 创建Table
|
||
/// </summary>
|
||
/// <param name="tableName"></param>
|
||
/// <param name="columns"></param>
|
||
/// <param name="addPID"></param>
|
||
/// <param name="primaryKey"></param>
|
||
public void CreateTable(string tableName, Dictionary<string, Type> columns, string primaryKey, Type primaryKeyType)
|
||
{
|
||
string sql = "";
|
||
|
||
DbDataReader dataReader = _dataBase.ExecuteReader($"select column_name from information_schema.columns where table_name = '{tableName}'");
|
||
if (!dataReader.HasRows)
|
||
{
|
||
if (!string.IsNullOrEmpty(primaryKey) && primaryKeyType != null && !columns.Keys.Contains(primaryKey))
|
||
{
|
||
sql += _dataBase.GetSqlByNameType(primaryKey, primaryKeyType);
|
||
sql += ',';
|
||
}
|
||
|
||
//列名
|
||
foreach (KeyValuePair<string, Type> column in columns)
|
||
{
|
||
sql += _dataBase.GetSqlByNameType(column.Key, column.Value);
|
||
sql += ',';
|
||
}
|
||
|
||
if (string.IsNullOrEmpty(sql))
|
||
{
|
||
return;
|
||
}
|
||
|
||
//主键
|
||
if (!string.IsNullOrEmpty(primaryKey))
|
||
{
|
||
sql += $"CONSTRAINT \"{tableName}_pkey\" PRIMARY KEY (\"{primaryKey}\" )";
|
||
}
|
||
else
|
||
{
|
||
if (!string.IsNullOrEmpty(sql) && sql.LastIndexOf(',') == sql.Length - 1)
|
||
{
|
||
sql = sql.Remove(sql.Length - 1);
|
||
}
|
||
}
|
||
|
||
sql = $"CREATE TABLE \"{tableName}\"({sql}) WITH ( OIDS=FALSE );";
|
||
|
||
sql += $"ALTER TABLE \"{tableName}\" OWNER TO postgres;";
|
||
|
||
//表的Select权限授权给postgres用户
|
||
sql += $"GRANT SELECT ON TABLE \"{tableName}\" TO postgres;";
|
||
|
||
_dataBase.ExecuteNonQuery(sql);
|
||
}
|
||
}
|
||
|
||
public void CreateTableIndex(string table, string index, string sql)
|
||
{
|
||
DbDataReader dataReader = _dataBase.ExecuteReader("select* from pg_indexes where tablename='" + table + "' and indexname = '" + index + "'");
|
||
if (!dataReader.HasRows)
|
||
{
|
||
ExecuteNonQuery(sql);
|
||
}
|
||
}
|
||
|
||
private void UpdateTable()
|
||
{
|
||
CreateTableIndex("recipe_step_data", "recipe_step_data_idx1", "CREATE INDEX recipe_step_data_idx1 ON public.recipe_step_data USING btree(\"process_data_guid\", \"step_number\");");
|
||
|
||
CreateTableIndex("step_fdc_data", "step_fdc_data_idx1", "CREATE INDEX step_fdc_data_idx1 ON public.step_fdc_data USING btree(\"process_data_guid\", \"step_number\");");
|
||
|
||
CreateTableIndex("lot_wafer_data", "lot_wafer_data_idx1", "CREATE INDEX lot_wafer_data_idx1 ON public.lot_wafer_data USING btree(lot_data_guid COLLATE pg_catalog.\"default\", wafer_data_guid COLLATE pg_catalog.\"default\");");
|
||
|
||
//AddTableColumn("carrier_data", new Dictionary<string, Type>
|
||
//{
|
||
// {"rootname",typeof(string) },
|
||
// {"recipename",typeof(string)},
|
||
// {"filedetail",typeof(byte[]) }
|
||
//});
|
||
|
||
//AlterTableColumn("carrier_data", new Dictionary<string, string>
|
||
//{
|
||
// {"rootname","rootname1" },
|
||
// {"recipename","recipename1"},
|
||
// {"filedetail","filedetail1" }
|
||
//});
|
||
|
||
//DeleteTableColumn("carrier_data", new List<string>
|
||
//{
|
||
// "rootname1",
|
||
// "recipename1",
|
||
// "filedetail1"
|
||
//});
|
||
}
|
||
|
||
/// <summary>
|
||
/// 新增Table列名
|
||
/// </summary>
|
||
/// <param name="tableName"></param>
|
||
/// <param name="columns"></param>
|
||
public void AddTableColumn(string tableName, Dictionary<string, Type> columns)
|
||
{
|
||
string sql = $"select column_name from information_schema.columns where table_name = '{tableName}';";
|
||
DbDataReader dataReader = _dataBase.ExecuteReader(sql);
|
||
string cmdText = string.Empty;
|
||
List<string> list = new List<string>();
|
||
while (dataReader.Read())
|
||
{
|
||
for (int i = 0; i < dataReader.FieldCount; i++)
|
||
{
|
||
list.Add(dataReader[i].ToString());
|
||
}
|
||
}
|
||
|
||
if (list.Count > 0)
|
||
{
|
||
foreach (KeyValuePair<string, Type> 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);
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 更新Table列名
|
||
/// </summary>
|
||
/// <param name="tableName"></param>
|
||
/// <param name="columns"></param>
|
||
public void AlterTableColumn(string tableName, Dictionary<string, string> columns)
|
||
{
|
||
string sql = $"select column_name from information_schema.columns where table_name = '{tableName}';";
|
||
DbDataReader dataReader = _dataBase.ExecuteReader(sql);
|
||
string cmdText = string.Empty;
|
||
List<string> list = new List<string>();
|
||
while (dataReader.Read())
|
||
{
|
||
for (int i = 0; i < dataReader.FieldCount; i++)
|
||
{
|
||
list.Add(dataReader[i].ToString());
|
||
}
|
||
}
|
||
|
||
if (list.Count > 0)
|
||
{
|
||
foreach (KeyValuePair<string, string> 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<string> columns)
|
||
{
|
||
string sql = $"select column_name from information_schema.columns where table_name = '{tableName}';";
|
||
DbDataReader dataReader = _dataBase.ExecuteReader(sql);
|
||
string cmdText = string.Empty;
|
||
List<string> list = new List<string>();
|
||
while (dataReader.Read())
|
||
{
|
||
for (int i = 0; i < dataReader.FieldCount; i++)
|
||
{
|
||
list.Add(dataReader[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 string GetSqlByNameType(string name, Type type)
|
||
{
|
||
return _dataBase.GetSqlByNameType(name, type);
|
||
}
|
||
|
||
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 int ExecuteNonQuery(string sql, string[] columnsName, params object[] args)
|
||
{
|
||
return _dataBase.ExecuteNonQuery(sql, columnsName, args);
|
||
}
|
||
|
||
public object ExecuteScalar(string sql, bool isChangeDB = true)
|
||
{
|
||
return _dataBase.ExecuteScalar(sql, isChangeDB);
|
||
}
|
||
|
||
public DataSet ExecuteDataSet(string sql)
|
||
{
|
||
return _dataBase.ExecuteDataSet(sql);
|
||
}
|
||
|
||
public DataTable ExecuteDataTable(string sql)
|
||
{
|
||
return _dataBase.ExecuteDataTable(sql);
|
||
}
|
||
|
||
public bool ExcuteTransAction(List<string> sqlList)
|
||
{
|
||
return _dataBase.ExcuteTransAction(sqlList);
|
||
}
|
||
|
||
private bool Monitor()
|
||
{
|
||
try
|
||
{
|
||
if (_sqlQueue.Count == 0)
|
||
{
|
||
return true;
|
||
}
|
||
|
||
if (_sqlQueue.TryDequeue(out string sql))
|
||
{
|
||
_dataBase.ExecuteNonQuery(sql);
|
||
}
|
||
|
||
return true;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LOG.Error(ex.Message, ex);
|
||
return true;
|
||
}
|
||
}
|
||
|
||
public void Terminate()
|
||
{
|
||
_monitorJob?.Stop();
|
||
_monitorJob = null;
|
||
|
||
_databaseCleaner?.Terminate();
|
||
}
|
||
|
||
/// <summary>
|
||
/// DataTable转成List
|
||
/// </summary>
|
||
/// <typeparam name="T"></typeparam>
|
||
/// <param name="dt"></param>
|
||
/// <returns></returns>
|
||
public IList<T> DataTableToList<T>(DataTable dt) where T : new()
|
||
{
|
||
IList<T> list = new List<T>();
|
||
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;
|
||
}
|
||
|
||
/// <summary>
|
||
/// DataTable转成T
|
||
/// </summary>
|
||
/// <typeparam name="T"></typeparam>
|
||
/// <param name="dt"></param>
|
||
/// <returns></returns>
|
||
public T DataTableToObject<T>(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;
|
||
}
|
||
}
|
||
}
|