用 Oracle.ManagedDataAccess 连接 Oracle 数据库
推荐直接使用
Oracle.ManagedDataAccess(ODP.NET Managed Driver),它不依赖 Oracle 客户端安装,纯 .NET 实现,部署简单。NuGet 包名就是
Oracle.ManagedDataAccess,不是旧版的
System.Data.OracleClient(已弃用)或需要本地 Oracle Client 的
Oracle.DataAccess。
常见错误:项目里装了
Oracle.ManagedDataAccess.Core却在 .NET Framework 项目中引用 —— 这会导致运行时报
Could not load file or assembly 'Oracle.ManagedDataAccess'。注意区分:
.Core仅用于 .NET Core / .NET 5+;传统 .NET Framework 项目必须用非
.Core版本。 在 Visual Studio 中右键项目 → “管理 NuGet 包” → 搜索并安装
Oracle.ManagedDataAccess(无 .Core 后缀) 连接字符串格式示例:
"User Id=myuser;Password=mypass;Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=myhost)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=orcl)))"若使用 TNS 别名(如
ORCL),确保
tnsnames.ora在应用可访问路径下,或改用 EZConnect 格式:
"User Id=myuser;Password=mypass;Data Source=myhost:1521/orcl"
写一个最小可用的 OracleConnection 打开测试
别一上来就写 ORM 或封装类,先验证驱动和连接是否通。重点看
Open()是否抛异常,以及异常类型 —— 大部分连不上都是连接字符串或网络问题,不是代码逻辑问题。
using Oracle.ManagedDataAccess.Client;
<p>string connStr = "User Id=scott;Password=tiger;Data Source=localhost:1521/orcl";
using (var conn = new OracleConnection(connStr))
{
try
{
conn.Open();
Console.WriteLine("✅ 连接成功,版本:" + conn.ServerVersion);
}
catch (OracleException ex)
{
Console.WriteLine("❌ Oracle 错误:" + ex.Number + " - " + ex.Message);
}
catch (Exception ex)
{
Console.WriteLine("❌ 其他异常:" + ex.Message);
}
}注意:
OracleException的
Number字段很关键,比如
ORA-12154是解析不到服务名,
ORA-12541是监听器没响应,
ORA-01017是用户名密码错 —— 这些数字比错误消息更可靠,适合日志分类。
执行查询时要注意参数命名和数据类型
Oracle 的参数前缀是冒号
:,不是 @ 或 ?,且**大小写敏感**。同时,
OracleParameter的
OracleDbType显式指定类型比靠推断更稳,尤其对
CLOB、
DATE、
NUMBER等易出错类型。 参数名必须带冒号:
cmd.Parameters.Add(new OracleParameter(":id", 123)),写成 "id"或
"@id"都会报
ORA-01036查询含中文或特殊字符时,确保数据库字符集(如 AL32UTF8)与客户端一致,否则
GetString()可能乱码
OracleCommand.CommandTimeout默认是 30 秒,长查询记得调大,否则超时后连接可能未释放
连接池默认开启,但要注意泄漏和状态残留
Oracle.ManagedDataAccess默认启用连接池,这很好,但容易掩盖
Connection忘记
Close()或
Dispose()的问题。连接池里的物理连接不会立刻关闭,而是回收复用 —— 表面看程序跑得动,实际可能耗尽池子(默认上限 100)。
典型症状:应用运行一段时间后,新请求卡住、超时,日志里反复出现
ORA-12519: no appropriate service handler found或
Timeout expired。 务必用
using块包裹
OracleConnection和
OracleCommand不要手动调用
ClearAllPools()除非真有连接状态污染(如 ALTER SESSION),它会强制所有连接重连,伤性能 可通过连接字符串加
Pooling=true;Min Pool Size=5;Max Pool Size=50;控制池行为
最常被忽略的是连接字符串里混用了不同用户、不同服务名但共用同一个连接池键 —— ODP.NET 会把它们当同一池,导致权限或 schema 错乱。每个独立业务场景建议用唯一连接字符串,或显式关池:
Pooling=false(仅调试用)。
