如何解決 Oracle ORA-00904: “FALSE” 無效的 ID 錯誤?完整解析與三種實戰方案
前言
在使用 .NET 與 Entity Framework Core 連接 Oracle 資料庫時,常會遇到一個看似莫名其妙的錯誤訊息:
OracleException: ORA-00904: "FALSE": 無效的 ID如果你不是資料庫專家,看到這裡可能會疑惑:「為什麼寫程式時只是用到 C# 裡的
false
,居然跑到 SQL 裡變成了 FALSE
,而 Oracle 不認得?」本篇文章將深入淺出,帶你了解其成因,並提供三種可行的解決方案,讓你快速排除故障、恢復正常開發流程。為什麼會發生 ORA-00904: “FALSE” 無效的 ID?
-
Oracle 不支援 Boolean
在 Oracle 的 SQL 語言裡,並沒有像TRUE
、FALSE
這樣的布林(Boolean)字面量。 -
EF Core Provider 自動翻譯
當你在 LINQ 查詢或投影中使用了 C# 的布林值(例如p => p.APS_DEAL ? "Y" : "N"
或直接把bool
欄位投影),Oracle 的 EF Core 外掛在產生 SQL 時,會把false
/true
翻譯成FALSE
/TRUE
,這就觸發了「無效的 ID」錯誤。
解法一:在記憶體端處理投影(Pull then Project)
概念:先把純資料實體取回(不帶任何方法呼叫),再用 LINQ-to-Objects 做 ToString()
、三元運算、bool→字串、格式化等邏輯。
// 1) 把實體一次查回 var plans = await _context.APSZPLANs .Where(p => p.APS_VERSION == apsVersion) .ToListAsync(); // 2) 在 C# 記憶體端再投影 var result = plans.Select(p => new APSZRESULTA { APS_PLAN_NO = p.APS_PLAN_NO, // 把布林轉成字串 APS_DEAL = p.APS_DEAL ? "Y" : "N", APS_DEAL_QTY = (p.APS_DEAL_QTY ?? 0).ToString("N0"), // 其他欄位同理… }).ToList();
優點:完全不會再觸發 Oracle 的 FALSE
/TRUE
,簡單易懂。
缺點:資料先拉大宗到客戶端,若筆數很多可能效能受影響。
解法二:在查詢中插入 .AsEnumerable()
概念:透過 .AsEnumerable()
把查詢由 EF Core 轉為 LINQ-to-Objects,之後的 Select
都在記憶體裡執行。
var interim = await _context.APSZPLANs .Where(p => p.APS_VERSION == apsVersion) .OrderBy(p => p.APS_PLAN_NO) .AsEnumerable() // ← 斷開 EF Core 翻譯 .Select(p => new APSZRESULTA { APS_PLAN_NO = p.APS_PLAN_NO, APS_DEAL = p.APS_DEAL ? "Y" : "N", APS_DEAL_QTY = (p.APS_DEAL_QTY ?? 0).ToString("N0"), // …其他欄位 }) .ToListAsync();優點:比第一種方法更有彈性,能保留 SQL 的
WHERE
、ORDER BY
。缺點:在
AsEnumerable()
之前撈出的資料量仍會傳到客戶端。解法三:使用 EF Core ValueConverter 將 Boolean 映射成數字或字串
概念:在 OnModelCreating
中,透過 ValueConverter 把 C# 的 bool
欄位映成 Oracle 能接受的型別(如 NUMBER(1)
或 CHAR(1)
)。
protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity() .Property(e => e.APS_DEAL) .HasConversion( v => v ? 1 : 0, // C# → 資料庫 存成 0/1 v => v == 1 // 資料庫 → C# 還原成 bool ) .HasColumnType("NUMBER(1)"); }
優點:資料庫層面就統一將布林轉 0/1,不需額外在每個查詢裡寫三元運算。
缺點:需調整 DbContext
映射設定,對現有資料庫 schema 可能有影響。
小結與建議
-
如果專案筆數規模不大,建議優先選擇 解法一 或 解法二,最快速解決 SQL 產生
FALSE
的問題。 -
如果你希望長期維護更乾淨的映射,並避免在各處重複轉換邏輯,可考慮 解法三,在
OnModelCreating
做一次性設定。
了解了 Oracle 不支援 Boolean,並掌握上述三種策略,就能有效消除 ORA-00904: "FALSE": 無效的 ID
,讓你的 .NET + EF Core 應用平穩運作。
留言
張貼留言