🛠【ASP.NET Core + Oracle】解決 ORA-00904 "FALSE": 無效的 ID 錯誤與資料欄位動態插入顯示問題
🔍 問題描述
在開發群創光電內部的 APS 排程系統(使用 ASP.NET Core + Vue 3 + Oracle),前端發生多筆錯誤訊息:
Request failed with status code 500 Oracle.ManagedDataAccess.Client.OracleException: ORA-00904: "FALSE": 無效的 ID
這是 Oracle 資料庫對布林值處理不一致造成的錯誤,我們後端嘗試將某個欄位
.Where(x => x.FLAG == false)
寫法,經由 EF Core 轉成 SQL:
SELECT * FROM TABLE WHERE FLAG = FALSE
而 Oracle 並不支援
FALSE
關鍵字作為布林值 →
導致查詢失敗。
🔧 解決方案 1:避免布林值直接進入 LINQ to SQL
EF Core + Oracle 不支援下列語法:
.Where(x => x.IsActive == false) // ❌ Oracle 無法解析 FALSE
✅ 解法:將布林判斷移至
.ToList()
之後,變成記憶體篩選:
var list = await db.Table.Where(x => x.Version == ver).ToListAsync(); var filtered = list.Where(x => !x.IsActive).ToList(); // ✅ 在記憶體中比對布林
🔧 解決方案 2:安全轉換 SEQ_NO 為 Decimal
後端為了將前段表 APSZFRONT
的
SEQ_NO
與
APSZLCM
的
APS_PLAN_SEQ
對應,用到了這段程式碼:
Convert.ToDecimal(front.SEQ_NO)
但一旦
SEQ_NO
含有英文字母(例如
GN140CHCAAE90S_20250811_1_531
),就會丟出 FormatException
→
造成 HTTP 500。
✅ 正確寫法(TryParse 避免失敗):
decimal seqNoDecimal; bool isValidSeq = decimal.TryParse(front.SEQ_NO, out seqNoDecimal); var matchedPlants = isValidSeq ? lcmList.Where(l => l.APS_PLAN_NO == front.APS_PLAN_NO && l.APS_PLAN_SEQ == seqNoDecimal).ToList() : new List<string>();
✨ 顯示格式進階處理:將 PLANT 插入 SITE 和 APPL 中間
客戶需求是將 APSZLCM 表的
PLANT
插入到
SITE
與
APPL
中間顯示,例如:
原本: SITE = "NGB" APPL = "NB" PLANT = "WF01" → 顯示:NGB WF01 NB
✅ 實作如下:
SITE = $"{front.SITE ?? ""} {plantString} {front.APPL ?? ""}".Trim()
若要顯示在獨立欄位「PLANT」,且不帶括號,請這樣寫:
var plantString = string.Join("/", matchedPlants.Where(p => !string.IsNullOrWhiteSpace(p)));
✅ 成功顯示結果(已排除錯誤)
-
❌ 原錯誤:500 Internal Server Error
-
✅ 修改後:資料成功顯示,且
PLANT
欄位為純文字(無括號)
📦 技術堆疊
技術 | 說明 |
---|---|
ASP.NET Core | 後端 REST API |
Oracle DB | 使用 Oracle.ManagedDataAccess |
EF Core | 資料存取 ORM |
Vue 3 | 前端資料表、Excel 匯出功能 |
Axios | API 呼叫 |
XLSX.js | 資料匯出千分位格式處理 |
🧠 開發者心得
Oracle 不像 SQL Server 一樣支援
TRUE
/FALSE
,只接受 0/1
或
Y/N
。開發時需留意:
-
.Where()
不要帶入布林條件 -
Convert.ToDecimal()
只能用在確定數值格式的字串 -
Vue 前端欄位動態合併時,欄位命名應保持清楚(避免
SITE
出現混淆資訊)
留言
張貼留言