iT邦幫忙

2

🖥️ Oracle連線與主機監測:用 .ashx 實作簡單但實用的健康檢查頁面

  • 分享至 

  • xImage
  •  

https://ithelp.ithome.com.tw/upload/images/20250616/20155103Uq0ONVkAoZ.png

🧪 問題是從一段「查不到資料」開始的

在維護 EIP 系統的排程服務時,我想要讓 .ashx 能定期自動檢查主機或 Oracle 是否連得上。因此,我設計了一張名為 SCH_HOST_CHECK_LIST 的資料表,記錄所有要檢查的目標(IP、URL、Oracle 連線字串),並且讓程式讀取這張表後根據不同類型執行對應檢查。

一切看似順利,但我在執行 .ashx 測試時,意外發現:

雖然 SQL 在 SQL Developer 中查得到資料,
但程式卻始終回傳「查不到」。

這讓我開始排查可能的原因。


🔍 原因:INSERT 沒有 COMMIT 的隱形地雷

當我仔細比對查詢與權限設定時,發現:

我確實有成功下 INSERT,但忘了 COMMIT

Oracle 的每一個 session 都是獨立的,如果沒有明確提交,其他程式(另一個 session)是完全看不到這些資料的。這對開發測試階段來說,可能是一個很容易忽略的陷阱。

✅ 解法也很單純:記得在 SQL 編輯器或初始化資料腳本中,補上 COMMIT;


⚙️ 優化:讓 TestConnection.ashx 更通用與穩定

原本我在 TestConnection.ashx 中只用一行 SQL 測試:

string testSql = "SELECT CRDAT FROM EIP.SCH_HOST_CHECK_LIST WHERE ROWNUM = 1";

但當資料表不存在時就會報錯。因此我加入了兩個優化方向:

先檢查資料表是否存在

再檢查資料是否可讀

把 SCHEMA 與 TABLE 設為變數,方便未來共用

更新後的檢查順序如下:

string schema = "EIP";
string table = "SCH_HOST_CHECK_LIST";
string column = "CRDAT";

string checkTableSql = string.Format(
    "SELECT COUNT(*) FROM ALL_TABLES WHERE OWNER = '{0}' AND TABLE_NAME = '{1}'", 
    schema, table);

string testSql = string.Format(
    "SELECT {2} FROM {0}.{1} WHERE ROWNUM = 1", 
    schema, table, column);

最後印出目前登入者、資料庫名稱、呼叫主機等資訊,協助 debug。

✅ 實用的錯誤排查方式
在這次經驗中,我整理出一份「程式能執行但資料為空」的排查清單:

✔ 是否真的 COMMIT?

✔ 程式與資料庫帳號是否一致?

✔ 權限是否已授予?

✔ 使用的 DBList 與實際資料庫是否一致?

✔ SYS_CONTEXT('USERENV', ...) 是否能印出目前環境資訊?

這些簡單但實用的排查動作,幫我省下不少時間。

🤖 想讓 GPT 協助你判斷資料為何撈不到?可以這樣問:
我用 SQL 查得到資料,但程式中 da.GetDataMutilRow(sql) 為空,可能是什麼原因?

⚙️ 文末附錄:TestConnection.ashx 原始碼

<%@ WebHandler Language="C#" Class="TestConnection" %>

using System;
using System.Web;

public class TestConnection : IHttpHandler
{
    public void ProcessRequest(HttpContext context)
    {
        context.Response.ContentType = "text/plain";
        context.Response.Write("🧪 Oracle 連線測試中...\n\n");

        // 可變動參數
        string schema = "EIP";
        string table = "SCH_HOST_CHECK_LIST";
        string column = "CRDAT";

        try
        {
            DataAccess da = new DataAccess();

            // 查詢目前登入的 Session 資訊
            string sqlSession = @"SELECT 
                SYS_CONTEXT('USERENV','SESSION_USER') AS SESSION_USER,
                SYS_CONTEXT('USERENV','CURRENT_SCHEMA') AS CURRENT_SCHEMA,
                SYS_CONTEXT('USERENV', 'DB_NAME') AS DB_NAME,
                SYS_CONTEXT('USERENV','HOST') AS HOST,
                SYS_CONTEXT('USERENV','IP_ADDRESS') AS IP
            FROM DUAL";

            var sessionInfo = da.GetDataOneRow(sqlSession);

            context.Response.Write(string.Format("📌 資料庫登入帳號:{0}\n", sessionInfo["SESSION_USER"]));
            context.Response.Write(string.Format("📌 SCHEMA:{0}\n", sessionInfo["CURRENT_SCHEMA"]));
            context.Response.Write(string.Format("📌 主機的 service:{0}\n", sessionInfo["DB_NAME"]));
            context.Response.Write(string.Format("📌 呼叫端主機名稱:{0}\n", sessionInfo["HOST"]));
            context.Response.Write(string.Format("📌 呼叫端IP:{0}\n\n", sessionInfo["IP"]));

            // 檢查資料表是否存在
            string checkTableSql = string.Format(
                "SELECT COUNT(*) FROM ALL_TABLES WHERE OWNER = '{0}' AND TABLE_NAME = '{1}'",
                schema,
                table
            );

            string tableExists = da.GetDataOneValue(checkTableSql);

            if (tableExists == "0")
            {
                context.Response.Write(string.Format("❌ 資料表 {0}.{1} 不存在,請確認資料庫是否建立成功。\n", schema, table));
                return;
            }
            else
            {
                context.Response.Write(string.Format("✅ 資料表 {0}.{1} 存在\n", schema, table));
            }

            // 測試是否能 SELECT 一筆資料
            string testSql = string.Format("SELECT {2} FROM {0}.{1} WHERE ROWNUM = 1", schema, table, column);
            var row = da.GetDataOneRow(testSql);

            if (row.Count > 0)
            {
                context.Response.Write(string.Format("✔ 查到一筆 {0}.{1} 資料:{2}\n", schema, table, row[column]));
            }
            else
            {
                context.Response.Write(string.Format("⚠ 查不到 {0} 資料,請確認資料存在或權限開放。\n", table));
            }
        }
        catch (Exception ex)
        {
            context.Response.Write(string.Format("❌ 發生錯誤:{0}\n", ex.Message));
        }
    }

    public bool IsReusable { get { return false; } }
}

圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言