C# TransactionScope 与 OleDB 和 Oracle
C# TransactionScope with OleDB and Oracle
我当前的应用程序将所有数据库操作都放在一个带有连接的巨大 Using 语句中,以确保事务已完全提交或回滚,目前如果我有通用方法,它们将传递当前打开的 OleDbConnection,以便它可以用过的。
我想使用 TransactionScope 代替外部使用部分。请看下面我的测试代码:
private void Test() {
string _connectionString = "Provider=OraOLEDB.Oracle.1;Password=XXXXXXXX;Persist Security Info=True;User ID=XXXXXXXX;Data Source=XXXXXXX;min pool size=1;incr pool size=5;decr pool size=2;connection timeout=60;";
using (TransactionScope _ts = new TransactionScope(TransactionScopeOption.Required))
{
using (OleDbConnection _cn = new OleDbConnection(_connectionString))
{
_cn.Open(); // Errors Here!
using (OleDbCommand _cmd = new OleDbCommand())
{
_cmd.Connection = _cn;
_cmd.CommandText = "insert into testtable (TEST) values ('FIRST')";
_cmd.CommandType = CommandType.Text;
_cmd.ExecuteNonQuery();
}
}
using (OleDbConnection _cn = new OleDbConnection(_connectionString))
{
_cn.Open();
using (OleDbCommand _cmd = new OleDbCommand())
{
_cmd.Connection = _cn;
_cmd.CommandText = "insert into testtable (TEST) values ('SECOND')";
_cmd.CommandType = CommandType.Text;
_cmd.ExecuteNonQuery();
}
}
}
}
我收到的错误是 "Unable to enlist in the transaction." 我读到 Oracle 不喜欢使用 TransactionScope (Problems with TransactionScope and Oracle),但它似乎符合我需要实现的目标。我发现关于如何跨连接池连接桥接单个事务的信息很少。
编辑 - 2 月 11 日
我从 OleDB 切换到 ODP.Net 并设法排除了官方的 Oracle ORA 错误...
ORA-02048: attempt to begin distributed transaction without logging on
遗憾的是,据我所知,我认为这是一个 Oracle 错误?我发现论坛帖子暗示版本 10.2.0.2 有这个错误,但我在 10.2.0.4?
希望有人能帮忙!谢谢
所以,我的回答有两点:
首先我需要在我的客户端上安装OracleMTS 服务。其次,我从 OleDB(通过 Oracle.ManagedDataAccess v12)更改为 Oracle.DataAccess v11,并且有效!
我发现 ODP.Net 客户端的 v12 和 10.2.0.4 存在分布式事务失败的错误,但版本 11 有效。仍然对为什么它不能与 OleDB 一起工作感到困惑,但我现在已经解决了。希望这可以帮助其他人在我的位置!
要与 TransactionScope 一起使用,连接字符串必须包含“enlist=dynamic”
https://docs.oracle.com/database/121/ODPNT/InstallConfig.htm#r6c1-t14
Specifies whether the application enlists in distributed transactions explicitly after an OracleConnection.Open method invocation through EnlistTransaction() or EnlistDistributedTransaction(). To configure ODP.NET to enable dynamic enlistment programmatically, the connection string must contain "enlist=dynamic".
连接字符串例如:
enlist=dynamic;User Id=USER;Password=pass;Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=127.0.0.1)(PORT=1521)))(CONNECT_DATA=(SERVICE_NAME=TestDB)));
我当前的应用程序将所有数据库操作都放在一个带有连接的巨大 Using 语句中,以确保事务已完全提交或回滚,目前如果我有通用方法,它们将传递当前打开的 OleDbConnection,以便它可以用过的。
我想使用 TransactionScope 代替外部使用部分。请看下面我的测试代码:
private void Test() {
string _connectionString = "Provider=OraOLEDB.Oracle.1;Password=XXXXXXXX;Persist Security Info=True;User ID=XXXXXXXX;Data Source=XXXXXXX;min pool size=1;incr pool size=5;decr pool size=2;connection timeout=60;";
using (TransactionScope _ts = new TransactionScope(TransactionScopeOption.Required))
{
using (OleDbConnection _cn = new OleDbConnection(_connectionString))
{
_cn.Open(); // Errors Here!
using (OleDbCommand _cmd = new OleDbCommand())
{
_cmd.Connection = _cn;
_cmd.CommandText = "insert into testtable (TEST) values ('FIRST')";
_cmd.CommandType = CommandType.Text;
_cmd.ExecuteNonQuery();
}
}
using (OleDbConnection _cn = new OleDbConnection(_connectionString))
{
_cn.Open();
using (OleDbCommand _cmd = new OleDbCommand())
{
_cmd.Connection = _cn;
_cmd.CommandText = "insert into testtable (TEST) values ('SECOND')";
_cmd.CommandType = CommandType.Text;
_cmd.ExecuteNonQuery();
}
}
}
}
我收到的错误是 "Unable to enlist in the transaction." 我读到 Oracle 不喜欢使用 TransactionScope (Problems with TransactionScope and Oracle),但它似乎符合我需要实现的目标。我发现关于如何跨连接池连接桥接单个事务的信息很少。
编辑 - 2 月 11 日
我从 OleDB 切换到 ODP.Net 并设法排除了官方的 Oracle ORA 错误...
ORA-02048: attempt to begin distributed transaction without logging on
遗憾的是,据我所知,我认为这是一个 Oracle 错误?我发现论坛帖子暗示版本 10.2.0.2 有这个错误,但我在 10.2.0.4?
希望有人能帮忙!谢谢
所以,我的回答有两点:
首先我需要在我的客户端上安装OracleMTS 服务。其次,我从 OleDB(通过 Oracle.ManagedDataAccess v12)更改为 Oracle.DataAccess v11,并且有效!
我发现 ODP.Net 客户端的 v12 和 10.2.0.4 存在分布式事务失败的错误,但版本 11 有效。仍然对为什么它不能与 OleDB 一起工作感到困惑,但我现在已经解决了。希望这可以帮助其他人在我的位置!
要与 TransactionScope 一起使用,连接字符串必须包含“enlist=dynamic”
https://docs.oracle.com/database/121/ODPNT/InstallConfig.htm#r6c1-t14
Specifies whether the application enlists in distributed transactions explicitly after an OracleConnection.Open method invocation through EnlistTransaction() or EnlistDistributedTransaction(). To configure ODP.NET to enable dynamic enlistment programmatically, the connection string must contain "enlist=dynamic".
连接字符串例如:
enlist=dynamic;User Id=USER;Password=pass;Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=127.0.0.1)(PORT=1521)))(CONNECT_DATA=(SERVICE_NAME=TestDB)));