Browse Source

优化数据库链接

callm 21 hours ago
parent
commit
ab30484b38

+ 1 - 1
UAS_MES_YDCY/CustomControl/HeadBar/HeadBar.cs

@@ -122,7 +122,7 @@ namespace UAS_MES_NEW.CustomControl
                 if (logout_confirm == "Yes")
                 {
                     //注销的时候切换回默认数据库
-                    SystemInf.ConnectionString = "Connection Timeout=0;Pooling=false;Password=select!#%*(;User ID=YD_CYZZ;Pooling=false;Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=192.168.0.85)(PORT=1521)))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=orcl)));";
+                    SystemInf.ConnectionString = "Connection Timeout=30;Pooling=true;Min Pool Size=2;Max Pool Size=8;Connection Lifetime=300;Password=select!#%*(;User ID=YD_CYZZ;Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=192.168.0.85)(PORT=1521)))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=orcl)));";
                     DataHelper.DBConnectionString = SystemInf.ConnectionString;
                     //清除上个用户的权限信息
                     SystemInf.Caller.Clear();

+ 84 - 8
UAS_MES_YDCY/DataOperate/DataHelper.cs

@@ -10,12 +10,15 @@ namespace UAS_MES_NEW.DataOperate
     class DataHelper
     {
         //系统默认的的连接字符串
-        private string ConnectionStrings = "Connection Timeout=0;Pooling=false;Password=select!#%*(;User ID=YD_CYZZ;Pooling=false;Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=192.168.0.85)(PORT=1521)))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=orcl)));";
+        private string ConnectionStrings = "Connection Timeout=30;Pooling=true;Min Pool Size=2;Max Pool Size=8;Connection Lifetime=300;Password=select!#%*(;User ID=YD_CYZZ;Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=192.168.0.85)(PORT=1521)))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=orcl)));";
         //用户选择的数据库的连接字符串
         public static string DBConnectionString;
         public static OracleConnection connection = null;
         OracleCommand command = null;
         int ReconnectTime = 0;
+        //记录当前 static connection 使用的连接串,用于检测账套切换
+        private static string currentConnString = null;
+
         /// <summary>
         /// 执行构造函数的时候打开数据库的链接
         /// </summary>
@@ -24,11 +27,28 @@ namespace UAS_MES_NEW.DataOperate
             try
             {
                 //如果选择的是默认数据则直接用配置文件的信息连接,否则选择数据库的账套信息
+                string targetConnString;
                 if (DBConnectionString == null || DBConnectionString == ConnectionStrings)
-                    connection = new OracleConnection(ConnectionStrings);
+                    targetConnString = ConnectionStrings;
                 else
-                    connection = new OracleConnection(DBConnectionString);
-                connection.Open();
+                    targetConnString = DBConnectionString;
+
+                //连接复用:仅当连接不存在/未打开/账套切换时才重建。
+                //原实现每次 new DataHelper() 都覆盖 static connection 新建物理连接,
+                //旧连接因窗体 dh 实例持有引用不被 GC,导致单客户端泄漏 20+ 个数据库会话。
+                if (connection == null || connection.State != ConnectionState.Open || currentConnString != targetConnString)
+                {
+                    try
+                    {
+                        if (connection != null)
+                            connection.Close();  //开启连接池后 Close 归还池,不再占用数据库会话
+                    }
+                    catch (Exception) { }
+
+                    connection = new OracleConnection(targetConnString);
+                    connection.Open();
+                    currentConnString = targetConnString;
+                }
             }
             catch (Exception e) { LogManager.DoLog(e.Message); }
         }
@@ -307,6 +327,36 @@ namespace UAS_MES_NEW.DataOperate
             return dt;
         }
 
+        /// <summary>
+        /// 通过表名,字段获取DataTable类型的数据(带行数上限,防止全表加载导致内存膨胀)
+        /// 列表类界面应优先使用此重载或已有的 getFieldsDatasByPageing,避免无限制 Fill 全表
+        /// </summary>
+        public DataTable getFieldsDatas(string TableName, string Fields, int maxRows)
+        {
+            DataTable dt = new DataTable();
+            string sql = "select " + Fields + " from " + TableName + " where rownum <= " + maxRows;
+            command = new OracleCommand(sql, connection);
+            Reconnect(command);
+            OracleDataAdapter ad = new OracleDataAdapter();
+            ad.SelectCommand = command;
+            try
+            {
+                ad.Fill(dt);
+            }
+            catch (Exception)
+            {
+                connection = new OracleConnection(DBConnectionString);
+                connection.Open();
+                command = new OracleCommand(sql, connection);
+                ad = new OracleDataAdapter();
+                ad.SelectCommand = command;
+                ad.Fill(dt);
+            }
+            ad.Dispose();
+
+            return dt;
+        }
+
         /// <summary>
         /// 根据DataTable和指定的表名更新数据,如果需要保存新增的数据则需要传递一条Insert的SQL
         /// </summary>
@@ -1147,15 +1197,41 @@ namespace UAS_MES_NEW.DataOperate
 
         public void Dispose()
         {
-
+            //command 为实例字段,可安全释放
+            if (command != null)
+            {
+                try { command.Dispose(); } catch (Exception) { }
+                command = null;
+            }
+            //connection 为 static 共享对象,开启连接池后由连接池统一管理生命周期,
+            //此处不主动 Close 以避免影响其它正在使用该连接的实例
         }
 
         private void Reconnect(OracleCommand cmd)
         {
-            if (cmd.Connection.State == ConnectionState.Closed)
+            //先确保连接对象存在,避免null引用
+            if (cmd.Connection == null)
             {
-                cmd.Connection.Open();
-                LogManager.DoLog("超时重连");
+                cmd.Connection = new OracleConnection(string.IsNullOrEmpty(DBConnectionString) ? ConnectionStrings : DBConnectionString);
+            }
+            ConnectionState state = cmd.Connection.State;
+            //Closed/Broken 才需要重连,正常状态直接返回,减少无谓的异常触发
+            if (state == ConnectionState.Closed || state == ConnectionState.Broken)
+            {
+                try
+                {
+                    if (state == ConnectionState.Broken)
+                    {
+                        cmd.Connection.Close();
+                    }
+                    cmd.Connection.Open();
+                    LogManager.DoLog("连接状态异常(" + state + ")已重连");
+                }
+                catch (Exception ex)
+                {
+                    LogManager.DoLog("重连失败:" + ex.Message);
+                    throw;
+                }
             }
         }
     }

+ 2 - 1
UAS_MES_YDCY/DataOperate/ExcelHandler.cs

@@ -9,12 +9,13 @@ using System.Text;
 using NPOI.SS.Util;
 using System.Drawing;
 using System.Collections.Generic;
+using UAS_MES_NEW.Entity;
 
 namespace UAS_MES_NEW.DataOperate
 {
     class ExcelHandler
     {
-        DataHelper dh = new DataHelper();
+        DataHelper dh = SystemInf.dh;
         /// <summary>
         /// 导出Excel,返回文件在客户端的路径
         /// </summary>

+ 1 - 1
UAS_MES_YDCY/FunctionCode/Packing/Packing_NewPallet.cs

@@ -38,7 +38,7 @@ namespace UAS_MES_NEW.Packing
 
         private void Make_NewPallet_Load(object sender, EventArgs e)
         {
-            dh = new DataHelper();
+            dh = SystemInf.dh;
             pr_code.FormName = Name;
             pr_code.SetValueField = new string[] { "pr_code" };
             pr_code.TableName = "product";

+ 2 - 2
UAS_MES_YDCY/FunctionCode/Query/Query_SOP_CY.cs

@@ -22,7 +22,7 @@ namespace UAS_MES_NEW.Query
 {
     public partial class Query_SOP_CY : Form
     {
-        DataHelper dh = new DataHelper();
+        DataHelper dh = SystemInf.dh;
 
         AutoSizeFormClass asc = new AutoSizeFormClass();
 
@@ -102,7 +102,7 @@ namespace UAS_MES_NEW.Query
                     {
                         try
                         {
-                            DataHelper dh = new DataHelper();
+                            DataHelper dh = SystemInf.dh;
                             if (!Directory.Exists(Application.StartupPath + @"\" + ps_prodcode.Text))
                             {
                                 Directory.CreateDirectory(Application.StartupPath + @"\" + ps_prodcode.Text);

+ 1 - 1
UAS_MES_YDCY/FunctionCode/SMT/SMT_Feeding.cs

@@ -60,7 +60,7 @@ namespace UAS_MES_NEW.SMT
         {
             de_table.Text = "全部";
             asc.controllInitializeSize(this);
-            dh = new DataHelper();
+            dh = SystemInf.dh;
             //机台编号
             de_code.FormName = Name;
             de_code.SetValueField = new string[] { "ma_code", "de_runstatus", "de_code", "de_table" };

+ 2 - 1
UAS_MES_YDCY/FunctionCode/SMT/SMT_MaterialsWaring.cs

@@ -6,6 +6,7 @@ using System.Windows.Forms;
 using System.Collections.Generic;
 using UAS_MES_NEW.DataOperate;
 using UAS_MES_NEW.PublicMethod;
+using UAS_MES_NEW.Entity;
 
 namespace UAS_MES_NEW.SMT
 {
@@ -30,7 +31,7 @@ namespace UAS_MES_NEW.SMT
 
         private void 用料预警_Load(object sender, EventArgs e)
         {
-            dh = new DataHelper();
+            dh = SystemInf.dh;
             asc.controllInitializeSize(this);
         }
 

+ 1 - 1
UAS_MES_YDCY/FunctionCode/SMT/SMT_WaringSetting.cs

@@ -11,7 +11,7 @@ namespace UAS_MES_NEW.SMT
     {
         StringBuilder sql = new StringBuilder();
 
-        DataHelper dh = new DataHelper();
+        DataHelper dh = SystemInf.dh;
 
         public SMT_WaringSetting()
         {

+ 2 - 1
UAS_MES_YDCY/FunctionCode/SystemSetting/SystemSetting_LabelMaintain.cs

@@ -12,6 +12,7 @@ using UAS_MES_NEW.DataOperate;
 using UAS_MES_NEW.Properties;
 using UAS_MES_NEW.PublicForm;
 using UAS_MES_NEW.PublicMethod;
+using UAS_MES_NEW.Entity;
 
 namespace UAS_MES_NEW.SystemSetting
 {
@@ -93,7 +94,7 @@ namespace UAS_MES_NEW.SystemSetting
         private void 条码维护_Load(object sender, EventArgs e)
         {
             asc.controllInitializeSize(this);
-            dh = new DataHelper();
+            dh = SystemInf.dh;
             condition.Append(" ");
             LoadData();
             //加loading框

+ 5 - 8
UAS_MES_YDCY/Login.cs

@@ -48,7 +48,7 @@ namespace UAS_MES_NEW
         {
             BaseUtil.FormStepInOrOut(this, true);
             //设置默认数据库
-            SystemInf.DefaultDB = "Connection Timeout=0;Pooling=false;Password=select!#%*(;User ID=YD_CYZZ;Pooling=false;Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=192.168.0.85)(PORT=1521)))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=orcl)));";
+            SystemInf.DefaultDB = "Connection Timeout=30;Pooling=true;Min Pool Size=2;Max Pool Size=8;Connection Lifetime=300;Password=select!#%*(;User ID=YD_CYZZ;Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=192.168.0.85)(PORT=1521)))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=orcl)));";
             SystemInf.ProcessesID = System.Diagnostics.Process.GetCurrentProcess().Id;
             CheckForIllegalCrossThreadCalls = false;
             LoadMasterInf = new Thread(LoadMaster);
@@ -95,7 +95,7 @@ namespace UAS_MES_NEW
             //设置选中数据库的链接
             string DBUser = DB.SelectedValue.ToString().Split('#')[0];
             string Address = DB.SelectedValue.ToString().Split('#')[1];
-            DataHelper.DBConnectionString = "Password=select!#%*(;User ID=" + DBUser + ";Pooling=false;Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=192.168.0.85)(PORT=1521)))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=orcl)));";
+            DataHelper.DBConnectionString = "Connection Timeout=30;Pooling=true;Min Pool Size=2;Max Pool Size=8;Connection Lifetime=300;Password=select!#%*(;User ID=" + DBUser + ";Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=192.168.0.85)(PORT=1521)))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=orcl)));";
             SystemInf.CurrentDB = DBUser;
             //设置屏幕的宽高信息
             SystemInf.ScreenWidth = Screen.PrimaryScreen.WorkingArea.Width;
@@ -243,15 +243,12 @@ namespace UAS_MES_NEW
 
         private void Login_Paint(object sender, PaintEventArgs e)
         {
+            //直接使用资源位图,避免每次重绘 new Bitmap 造成 GDI+ 频繁分配与 GC 压力
             Bitmap image = Resources.dialog_close_24px_1173781_easyicon_net;
-            Rectangle rect = this.ClientRectangle;
-            //画关闭符号
+            Point p5 = new Point(Width - Close_Size - 4, 4);
             using (Pen objpen = new Pen(Color.Black))
             {
-                //使用图片
-                Bitmap bt = new Bitmap(image);
-                Point p5 = new Point(Width - Close_Size - 4, 4);
-                e.Graphics.DrawImage(bt, p5);
+                e.Graphics.DrawImage(image, p5);
             }
         }
 

+ 1 - 1
UAS_MES_YDCY/Main.cs

@@ -351,7 +351,7 @@ namespace UAS_MES_NEW
             if (logout_confirm == "Yes")
             {
                 //注销的时候切换回默认数据库
-                SystemInf.ConnectionString = "Connection Timeout=0;Pooling=false;Password=select!#%*(;User ID=YD_CYZZ;Pooling=false;Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=192.168.0.85)(PORT=1521)))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=orcl)));";
+                SystemInf.ConnectionString = "Connection Timeout=30;Pooling=true;Min Pool Size=2;Max Pool Size=8;Connection Lifetime=300;Password=select!#%*(;User ID=YD_CYZZ;Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=192.168.0.85)(PORT=1521)))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=orcl)));";
                 DataHelper.DBConnectionString = SystemInf.ConnectionString;
                 //清除上个用户的权限信息
                 SystemInf.Caller.Clear();

+ 0 - 17
UAS_MES_YDCY/PublicMethod/LogicHandler.cs

@@ -1910,23 +1910,6 @@ namespace UAS_MES_NEW.PublicMethod
             dh.ExecuteSql(sql.ToString(), "insert", iType, iSN, iWeight, iUnit, iLineCode, iPrCode, iSource, iUser);
         }
 
-
-        public static bool CheckUpdate()
-        {
-            string version = BaseUtil.GetCacheData("Version").ToString();
-            DataHelper dh = new DataHelper();
-            string LastVersion = dh.getFieldDataByCondition("configs", "code", "caller='CSUPDATE'").ToString();
-            if (version == LastVersion || version == "" || LastVersion == "")
-            {
-                return false;
-            }
-            else
-            {
-                BaseUtil.SetCacheData("Version", LastVersion);
-                return true;
-            }
-        }
-
         /// <summary>
         /// 小箱装大箱的包装规则判断
         /// </summary>