我有一种情况,我在具有 TransactionScopeRequired=true 的 WCF 服务中运行,这意味着总会有环境事务。
但是,我需要在应用程序的整个生命周期内启动一个新连接,这意味着我不能让它使用环境事务。
关于如何做到这一点的任何想法?这样做会自动使用环境事务:
Assert.IsNotNull(System.Transactions.Transaction.Current);
var conn = new OracleConnection("my connection string");
conn.Open(); // <-- picks up ambient transaction, but I don't want that
实际上,这样说可以使示例更简单:
OracleConnection conn; // <-- this is actually held around in another object that has a very long lifetime, well past the TransactionScope.
using(var tx = new TransactionScope())
{
conn = new OracleConnection("my connection string");
conn.Open(); // <-- picks up ambient transaction, but I don't want that
// ... do stuff
}
我不希望我的连接实际拿起 TransactionScope。在实际代码中,在范围内执行数据库操作的还有很多事情要做,我只有 1 需要在事务范围的生命周期之后保留。
我想真实情况值得一提。这里实际发生的是,在 WCF 服务调用期间,我使用 Enterprise Library Caching 块将对象添加到缓存中。此对象是一个数据表,但也保持与已设置持续通知的 Oracle 的打开连接。这使我能够在底层 Oracle 表发生更改时自动刷新我的缓存数据集。
数据缓存项可以被任意数量的 WCF 初始化线程访问,所有这些线程都在它们自己的事务范围内运行。我想您可以将其视为将 OracleConnection 对象放入缓存中。更好的文本/示例代码块如下:
//beginning of a WCF service call
using (var tx = new TransactionScope())
{
var conn = new OracleConnection();
var cmd = new OracleCommand();
// set up OCN on the cmd and connection
var reader = cmd.ExecuteReader();
cache.Add("conn", conn);
cache.Add("cmd", cmd);
}
//beginning of a second wcf service call
using (var tx = new TransactionScope())
{
var conn = cache.Get("conn");
var cmd = cache.Get("cmd");
var reader = cmd.ExecuteReader();
// user reader to reload some data
}
重点是我有一个跨多个线程和事务范围的连接具有很长的生命周期。