CREATE OR REPLACE PACKAGE test_pkg AS
PROCEDURE test_pro(
p_input IN VARCHAR2,
p_output OUT NUMBER
);
END test_pkg;
/
CREATE OR REPLACE PACKAGE BODY test_pkg AS
PROCEDURE test_pro(p_input IN VARCHAR2, p_output OUT NUMBER) IS
BEGIN
-- 示範邏輯:回傳輸入字串長度
p_output := LENGTH(p_input);
END;
END test_pkg;
/
using System;
using System.Data;
using Oracle.ManagedDataAccess.Client; // 官方 Managed Driver
namespace OracleProcDemo
{
class Program
{
static string ConnStr = "User Id=scott;Password=tiger;Data Source=ORCL;";
static int ExecuteProc(string input)
{
int result = 0;
using (var conn = new OracleConnection(ConnStr))
using (var cmd = new OracleCommand("test_pkg.test_pro", conn))
{
cmd.CommandType = CommandType.StoredProcedure;
// 輸入參數
cmd.Parameters.Add("p_input", OracleDbType.Varchar2, input, ParameterDirection.Input);
// 輸出參數:必須指定型別與大小
var outParam = cmd.Parameters.Add("p_output", OracleDbType.Int32, ParameterDirection.Output);
// OracleDbType.Int32 對應 NUMBER,無需 Size
conn.Open();
cmd.ExecuteNonQuery();
// 取得輸出值
result = Convert.ToInt32(outParam.Value);
}
return result;
}
static void Main()
{
try
{
int len = ExecuteProc("Hello Oracle");
Console.WriteLine($"Input length: {len}"); // 輸出 12
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
}
}
}
| 項目 | 說明 |
|---|---|
| CommandType | CommandType.StoredProcedure |
| 參數命名 | 與 PL/SQL 參數名一致(不區分大小寫),建議加 p_ 前綴 |
| 輸出參數 | ParameterDirection.Output 或 InputOutput |
| OracleDbType | 必須精確對應:Varchar2, Int32, Decimal, Date, RefCursor 等 |
| REF CURSOR | OracleDbType.RefCursor,取得後轉 OracleDataReader |
| 陣列綁定 | 批次執行時使用 cmd.ArrayBindCount + 參數 Value 為陣列 |
cmd.Parameters 對應。Add。Data Source= (Easy Connect 或 TNS 別名);若用 TNS_ADMIN 確保環境變數正確。-- PL/SQL
PROCEDURE get_emps(p_deptno IN NUMBER, p_rc OUT SYS_REFCURSOR) IS
BEGIN
OPEN p_rc FOR SELECT * FROM emp WHERE deptno = p_deptno;
END;
-- C#
var rcParam = cmd.Parameters.Add("p_rc", OracleDbType.RefCursor, ParameterDirection.Output);
conn.Open();
cmd.ExecuteNonQuery();
using (var reader = ((OracleRefCursor)rcParam.Value).GetDataReader())
{
while (reader.Read()) Console.WriteLine(reader["ename"]);
}
使用 Oracle.ManagedDataAccess.Client 為官方推薦、無需安裝 Client 的純 .NET 驅動。核心在於:**精確對應參數型別、正確設定 Direction、using 區塊確保連線釋放**。掌握此模式即可涵蓋 90% 的預存程序呼叫場景。