2023-06-27 15:46:42 +08:00
using Aitex.Common.Util ;
using Aitex.Core.RT.Log ;
using Aitex.Core.Util ;
2023-04-13 11:51:03 +08:00
using System ;
using System.Collections.Generic ;
2023-06-27 15:46:42 +08:00
using System.Data.Common ;
2023-04-13 11:51:03 +08:00
using System.Data ;
using System.IO ;
2023-06-27 15:46:42 +08:00
using System.Linq ;
using System.Reflection ;
using System.Text ;
using System.Threading.Tasks ;
2023-06-28 15:29:13 +08:00
using Npgsql ;
2023-04-13 11:51:03 +08:00
namespace Aitex.Core.RT.DBCore
{
2023-06-27 15:46:42 +08:00
public class DataBaseManager : IDataBaseManager
{
2023-07-13 12:28:37 +08:00
private string _dbName = "sicdb" ;
2023-06-27 15:46:42 +08:00
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 ( ) ;
2023-07-10 18:21:15 +08:00
_monitorJob = new PeriodicJob ( 100 , Monitor , "DataBaseManager" , true ) ;
2023-06-27 15:46:42 +08:00
_databaseCleaner . Initialize ( ) ;
}
/// <summary>
/// 创建数据库
/// </summary>
public void CreateDataBase ( )
{
try
{
2023-07-10 18:21:15 +08:00
object obj = _dataBase . ExecuteScalar ( $"select datname from pg_catalog.pg_database where datname='{_dbName}'" , false ) ;
2023-06-27 15:46:42 +08:00
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>
2023-07-10 18:21:15 +08:00
public void CreateTable ( string tableName , Dictionary < string , Type > columns , string primaryKey , Type primaryKeyType )
2023-06-27 15:46:42 +08:00
{
2023-07-10 18:21:15 +08:00
string sql = "" ;
2023-06-27 15:46:42 +08:00
DbDataReader dataReader = _dataBase . ExecuteReader ( $"select column_name from information_schema.columns where table_name = '{tableName}'" ) ;
if ( ! dataReader . HasRows )
{
2023-07-10 18:21:15 +08:00
if ( ! string . IsNullOrEmpty ( primaryKey ) & & primaryKeyType ! = null & & ! columns . Keys . Contains ( primaryKey ) )
{
sql + = _dataBase . GetSqlByNameType ( primaryKey , primaryKeyType ) ;
2023-07-24 11:18:29 +08:00
sql + = ',' ;
2023-07-10 18:21:15 +08:00
}
2023-06-27 15:46:42 +08:00
//列名
foreach ( KeyValuePair < string , Type > column in columns )
{
2023-07-10 18:21:15 +08:00
sql + = _dataBase . GetSqlByNameType ( column . Key , column . Value ) ;
2023-07-24 11:18:29 +08:00
sql + = ',' ;
2023-07-10 18:21:15 +08:00
}
if ( string . IsNullOrEmpty ( sql ) )
{
return ;
2023-06-27 15:46:42 +08:00
}
//主键
2023-07-10 18:21:15 +08:00
if ( ! string . IsNullOrEmpty ( primaryKey ) )
2023-06-27 15:46:42 +08:00
{
2023-07-10 18:21:15 +08:00
sql + = $"CONSTRAINT \" { tableName } _pkey \ " PRIMARY KEY (\"{primaryKey}\" )" ;
2023-06-27 15:46:42 +08:00
}
else
{
2023-07-10 18:21:15 +08:00
if ( ! string . IsNullOrEmpty ( sql ) & & sql . LastIndexOf ( ',' ) = = sql . Length - 1 )
{
sql = sql . Remove ( sql . Length - 1 ) ;
}
2023-06-27 15:46:42 +08:00
}
2023-07-10 18:21:15 +08:00
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 ) ;
2023-06-27 15:46:42 +08:00
}
}
2023-07-10 18:21:15 +08:00
public void CreateTableIndex ( string table , string index , string sql )
2023-06-28 15:29:13 +08:00
{
DbDataReader dataReader = _dataBase . ExecuteReader ( "select* from pg_indexes where tablename='" + table + "' and indexname = '" + index + "'" ) ;
if ( ! dataReader . HasRows )
{
ExecuteNonQuery ( sql ) ;
}
}
2023-06-27 15:46:42 +08:00
private void UpdateTable ( )
{
2023-06-28 15:29:13 +08:00
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\");" ) ;
2023-06-27 15:46:42 +08:00
//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}';" ;
2023-06-28 15:29:13 +08:00
DbDataReader dataReader = _dataBase . ExecuteReader ( sql ) ;
2023-06-27 15:46:42 +08:00
string cmdText = string . Empty ;
List < string > list = new List < string > ( ) ;
2023-06-28 15:29:13 +08:00
while ( dataReader . Read ( ) )
2023-06-27 15:46:42 +08:00
{
2023-06-28 15:29:13 +08:00
for ( int i = 0 ; i < dataReader . FieldCount ; i + + )
2023-06-27 15:46:42 +08:00
{
2023-06-28 15:29:13 +08:00
list . Add ( dataReader [ i ] . ToString ( ) ) ;
2023-06-27 15:46:42 +08:00
}
}
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}';" ;
2023-06-28 15:29:13 +08:00
DbDataReader dataReader = _dataBase . ExecuteReader ( sql ) ;
2023-06-27 15:46:42 +08:00
string cmdText = string . Empty ;
List < string > list = new List < string > ( ) ;
2023-06-28 15:29:13 +08:00
while ( dataReader . Read ( ) )
2023-06-27 15:46:42 +08:00
{
2023-06-28 15:29:13 +08:00
for ( int i = 0 ; i < dataReader . FieldCount ; i + + )
2023-06-27 15:46:42 +08:00
{
2023-06-28 15:29:13 +08:00
list . Add ( dataReader [ i ] . ToString ( ) ) ;
2023-06-27 15:46:42 +08:00
}
}
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}';" ;
2023-06-28 15:29:13 +08:00
DbDataReader dataReader = _dataBase . ExecuteReader ( sql ) ;
2023-06-27 15:46:42 +08:00
string cmdText = string . Empty ;
List < string > list = new List < string > ( ) ;
2023-06-28 15:29:13 +08:00
while ( dataReader . Read ( ) )
2023-06-27 15:46:42 +08:00
{
2023-06-28 15:29:13 +08:00
for ( int i = 0 ; i < dataReader . FieldCount ; i + + )
2023-06-27 15:46:42 +08:00
{
2023-06-28 15:29:13 +08:00
list . Add ( dataReader [ i ] . ToString ( ) ) ;
2023-06-27 15:46:42 +08:00
}
}
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 ) ;
}
}
}
2023-07-10 18:21:15 +08:00
public string GetSqlByNameType ( string name , Type type )
{
return _dataBase . GetSqlByNameType ( name , type ) ;
}
2023-06-27 15:46:42 +08:00
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 ) ;
}
2023-06-28 15:29:13 +08:00
public int ExecuteNonQuery ( string sql , string [ ] columnsName , params object [ ] args )
{
return _dataBase . ExecuteNonQuery ( sql , columnsName , args ) ;
}
2023-06-28 18:26:50 +08:00
public object ExecuteScalar ( string sql , bool isChangeDB = true )
2023-06-27 15:46:42 +08:00
{
2023-06-28 18:26:50 +08:00
return _dataBase . ExecuteScalar ( sql , isChangeDB ) ;
2023-06-27 15:46:42 +08:00
}
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 )
{
2023-07-10 18:21:15 +08:00
return true ;
2023-06-27 15:46:42 +08:00
}
if ( _sqlQueue . TryDequeue ( out string sql ) )
{
_dataBase . ExecuteNonQuery ( sql ) ;
}
return true ;
}
catch ( Exception ex )
{
LOG . Error ( ex . Message , ex ) ;
2023-07-10 18:21:15 +08:00
return true ;
2023-06-27 15:46:42 +08:00
}
}
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 ;
}
}
2023-04-13 11:51:03 +08:00
}