Pet*_*ete 7 c# sql-server oracle msdtc transactions
注意请参阅更新6.它有一个简单的应用程序,演示如何重新创建问题.
我是DTC的噩梦......我们的设置是我们有两个数据库; 一个SQL Server 2008数据库和一个Oracle数据库(11g,我相信).我已经安装了oracle MTS的东西.我将DTC配置为允许分布式事务.对Oracle表的所有访问都通过SQL Server数据库中与链接服务器中的Oracle表相对的视图进行.
(关于DTC配置:选中 - >网络DTC访问,允许远程客户端,允许入站,允许出站,相互身份验证(尝试所有3个选项),启用XA事务和启用SNA LU 6.2事务.DTC登录as NT AUTHORITY\NetworkService)
Our app is an ASP.NET MVC 4.0 app that calls into a number of WCF services to perform database work. Currently the web app and the WCF service share the same app pool (not sure if it's relevant, but just in case...)
Some of our services are transactional, others are not.
Each WCF service that is transactional has the following attribute on its interface:
[ServiceContract(SessionMode=SessionMode.Required)]
Run Code Online (Sandbox Code Playgroud)
and the following attribute on the method signatures in the interface:
[TransactionFlow(TransactionFlowOption.Allowed)]
Run Code Online (Sandbox Code Playgroud)
and the following attribute on every method implementations:
[OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
Run Code Online (Sandbox Code Playgroud)
In my data access layer, all the transactional methods are set up as follows:
using (IDbConnection conn = DbTools.GetConnection(_configStr, _connStr, true))
{
using (IDbCommand cmd = DbTools.GetCommand(conn, "SET XACT_ABORT ON"))
{
cmd.ExecuteNonQuery();
}
using (IDbCommand cmd = DbTools.GetCommand(conn, sql))
{
... Perform actual database work ...
}
}
Run Code Online (Sandbox Code Playgroud)
Services that are transactional call transactional DAL code. The idea was to keep the stuff that needs to be transactional (a few cases) separate from the stuff that doesn't need to be transactional (~95% of the cases).
There ought not be cases where transactional and non-transactional WCF methods are called from within a transaction (though I haven't verified this and this may be the cause of my problems. I'm not sure, which is part of why I'm asking here.)
As I mentioned before, in most cases, this all works fine.
Periodically, and I cannot identify what initiates it, I start getting errors. And once they start, pretty much everything starts failing for a while. Eventually things start working again. Not sure why... This is all in a test environment with a single user.
Sometimes the error is:
Unable to start a nested transaction for OLE DB provider "OraOLEDB.Oracle" for linked server "ORACLSERVERNAME". A nested transaction was required because the XACT_ABORT option was set to OFF.
这个消息,我猜是当我在事务中有非事务性的东西时正在发生,因为我没有设置XACT_ABORT非事务性代码(这完全可行,如果这将解决我的问题).
但是,大多数情况下,错误是这样的:
System.Data.SqlClient.SqlException(0x80131904):无法执行操作,因为链接服务器"ORACLSERVERNAME"的OLE DB提供程序"OraOLEDB.Oracle"无法启动分布式事务.
现在,最初我们只有SQL Server表上的事务,并且一切正常.直到我们为某些Oracle表添加了事务支持才开始失败.我知道Oracle事务有效.正如我所说,大部分时间,一切都只是笨拙的,然后有时它开始失败并且一直失败,直到它决定停止失败然后它再次起作用.
希望我能弄清楚如何将其作为"功能"出售给我的用户,但我并不乐观,所以我很乐意帮助您追踪它.如果我遗漏了任何重要信息,请告诉我.
更新1:我注意到我们的交易似乎没有设置DistributedIdentifier,所以我在EnsureDistributed()这篇博文中添加了方法:http://www.make-awesome.com/2010/04/forcibly-creating-a-分布式净交易/
而不是硬编码的Guid(这似乎会导致很多问题),我让它为每个事务生成一个新的Guid,这似乎有效,但它没有解决我的问题.我想知道是否缺乏DistribuedIdentifier指示其他一些潜在的问题.我以前从未处理过这样的环境,所以我不确定什么是"正常".
更新2:我注意到DistributedIdentifier没有传递给WCF.从客户端,我在Transaction.Current.TransactionInformation中有一个DistributedIdentifier和一个LocalIdentifier.然而,在WCF服务器中,只有一个LocalIdentifier集,它与客户端的Guid不同(这是有意义的,但我希望DistributedIdentifier可以通过).
更新3:似乎当我处于事务中失败时,即使在我关闭IIS之后,我也无法让DTC服务关闭并重新启动.例如,如果我进入组件服务并更改安全设置,然后单击"应用"或"确定",等待一段时间后,我会收到一条拨号,指出"未能重新启动MS DTC服务.请查看事件日志以获取更多详细信息".
在事件日志中,我得到了一系列事件:
1 (from MSDTC): "The MS DTC service is stopping"
2 (From MSSQL$SQLEXPRESS): "The connection has been lost with Microsoft Distributed Transaction
Coordinator (MS DTC). Recovery of any in-doubt distributed transactions
involving Microsoft Distributed Transaction Coordinator (MS DTC)
will begin once the connection is re-established. This is an
informational message only. No user action is required."
-- Folowed by these 3 identical messages
3 (from MSDTC Client 2): 'MSDTC encountered an error (HR=0x80000171) while attempting to establish a secure connection with system GCOVA38.'
4 (from MSDTC Client 2): 'MSDTC encountered an error (HR=0x80000171) while attempting to establish a secure connection with system GCOVA38.'
5 (from MSDTC Client 2): 'MSDTC encountered an error (HR=0x80000171) while attempting to establish a secure connection with system GCOVA38.'
6 (From MSDTC 2): MSDTC started with the following settings:
Security Configuration (OFF = 0 and ON = 1):
Allow Remote Administrator = 0,
Network Clients = 1,
Trasaction Manager Communication:
Allow Inbound Transactions = 1,
Allow Outbound Transactions = 1,
Transaction Internet Protocol (TIP) = 0,
Enable XA Transactions = 1,
Enable SNA LU 6.2 Transactions = 1,
MSDTC Communications Security = Mutual Authentication Required,
Account = NT AUTHORITY\NetworkService,
Firewall Exclusion Detected = 0
Transaction Bridge Installed = 0
Filtering Duplicate Events = 1
Run Code Online (Sandbox Code Playgroud)
This makes me wonder if there's something maybe holding a transaction open somewhere? I get the sense that there's some sort of, for lack of a better term, 'dangling transaction' that's not getting committed or rolled back. In every case where I use a TransactionScope, it's happening in a "using" statement, so everything ought to be either rolling back or committing. But I'm really starting to think that somehow, something's leaking...
Update 4: Related to Update 3. I am performing manual enlistment. Our connection string has "Enlist=false". DBTools.GetConnection() takes a boolean parameter that specifies whether or not to enlist the current transaction into the connection. I'm posting this update because, based on the stuff from Update 3, I'm wondering if, perhaps, connection that aren't supposed to be enlisting transactions are, somehow enlisting them.
public static IDbConnection GetConnection(string configString, string connectionString, bool enlistTransaction)
{
SqlConnection conn = new SqlConnection(connectionString);
conn.Open();
if (enlistTransaction && Transaction.Current != null)
{
conn.EnlistTransaction(Transaction.Current);
}
return conn;
}
public static IDbCommand GetCommand(IDbConnection conn, string command)
{
IDbCommand cmd = conn.CreateCommand();
cmd.CommandText = command;
return cmd;
}
Run Code Online (Sandbox Code Playgroud)
Update 5: I've managed to find a set of unit tests that, if I run the group, it always fails in the same place in the same test (but if I just run that test by itself, over and over, it doesn't fail. It has something to do with the tests running before it.) I managed to get some DTC Trace logs. Here's a log that shows the initial failing transaction. I'm showing some preceding transactions as well, in case seeing some sucecssful ones helps. The failing transaction begins at seq=1846.
pid=1244 ;tid=6284 ;time=10/15/2013-10:00:45.064 ;seq=1822 ;eventid=TRANSACTION_BEGUN ;tx_guid=49a79b73-66c0-48cb-abb1-8b657a2e3e4d ;"TM Identifier='(null) '" ;"transaction has begun, description :'<NULL>'"
pid=1244 ;tid=6284 ;time=10/15/2013-10:00:45.064 ;seq=1823 ;eventid=RM_ENLISTED_IN_TRANSACTION ;tx_guid=49a79b73-66c0-48cb-abb1-8b657a2e3e4d ;"TM Identifier='(null) '" ;"resource manager #1004 enlisted as transaction enlistment #1. RM guid = '344d3060-811c-4fc6-bab6-0eea76e3af3a'"
pid=1244 ;tid=6284 ;time=10/15/2013-10:00:45.064 ;seq=1824 ;eventid=RM_ENLISTED_IN_TRANSACTION ;tx_guid=49a79b73-66c0-48cb-abb1-8b657a2e3e4d ;"TM Identifier='(null) '" ;"resource manager #1004 enlisted as transaction enlistment #2. RM guid = '7b16851c-00a5-41dd-b59c-b003dcae08ec'"
pid=1244 ;tid=6284 ;time=10/15/2013-10:00:45.064 ;seq=1825 ;eventid=RM_ENLISTED_IN_TRANSACTION ;tx_guid=49a79b73-66c0-48cb-abb1-8b657a2e3e4d ;"TM Identifier='(null) '" ;"resource manager #1005 enlisted as transaction enlistment #3. RM guid = '72efe9cc-80f2-4a5b-9659-28b07987b600'"
pid=1244 ;tid=6284 ;time=10/15/2013-10:00:45.079 ;seq=1826 ;eventid=RECEIVED_COMMIT_REQUEST_FROM_BEGINNER ;tx_guid=49a79b73-66c0-48cb-abb1-8b657a2e3e4d ;"TM Identifier='(null) '" ;"received request to commit the transaction from beginner"
pid=1244 ;tid=6284 ;time=10/15/2013-10:00:45.079 ;seq=1827 ;eventid=RM_ISSUED_PREPARE ;tx_guid=49a79b73-66c0-48cb-abb1-8b657a2e3e4d ;"TM Identifier='(null) '" ;"prepare request issued to resource manager #1004 for transaction enlistment #1"
pid=1244 ;tid=6284 ;time=10/15/2013-10:00:45.079 ;seq=1828 ;eventid=RM_ISSUED_PREPARE ;tx_guid=49a79b73-66c0-48cb-abb1-8b657a2e3e4d ;"TM Identifier='(null) '" ;"prepare request issued to resource manager #1004 for transaction enlistment #2"
pid=1244 ;tid=6284 ;time=10/15/2013-10:00:45.079 ;seq=1829 ;eventid=RM_ISSUED_PREPARE ;tx_guid=49a79b73-66c0-48cb-abb1-8b657a2e3e4d ;"TM Identifier='(null) '" ;"prepare request issued to resource manager #1005 for transaction enlistment #3"
pid=1244 ;tid=8488 ;time=10/15/2013-10:00:45.079 ;seq=1830 ;eventid=RM_VOTED_COMMIT ;tx_guid=49a79b73-66c0-48cb-abb1-8b657a2e3e4d ;"TM Identifier='(null) '" ;"resource manager #1004 voted commit for transaction enlistment #2"
pid=1244 ;tid=8488 ;time=10/15/2013-10:00:45.079 ;seq=1831 ;eventid=RM_VOTED_COMMIT ;tx_guid=49a79b73-66c0-48cb-abb1-8b657a2e3e4d ;"TM Identifier='(null) '" ;"resource manager #1004 voted commit for transaction enlistment #1"
pid=1244 ;tid=8488 ;time=10/15/2013-10:00:45.079 ;seq=1832 ;eventid=RM_VOTED_READ_ONLY ;tx_guid=49a79b73-66c0-48cb-abb1-8b657a2e3e4d ;"TM Identifier='(null) '" ;"resource manager #1005 voted read-only for transaction enlistment #3"
pid=1244 ;tid=8488 ;time=10/15/2013-10:00:45.079 ;seq=1833 ;eventid=TRANSACTION_COMMITTED ;tx_guid=49a79b73-66c0-48cb-abb1-8b657a2e3e4d ;"TM Identifier='(null) '" ;"transaction has got committed"
pid=1244 ;tid=8488 ;time=10/15/2013-10:00:45.079 ;seq=1834 ;eventid=RM_ISSUED_COMMIT ;tx_guid=49a79b73-66c0-48cb-abb1-8b657a2e3e4d ;"TM Identifier='(null) '" ;"commit request issued to resource manager #1004 for transaction enlistment #1"
pid=1244 ;tid=8488 ;time=10/15/2013-10:00:45.079 ;seq=1835 ;eventid=RM_ISSUED_COMMIT ;tx_guid=49a79b73-66c0-48cb-abb1-8b657a2e3e4d ;"TM Identifier='(null) '" ;"commit request issued to resource manager #1004 for transaction enlistment #2"
pid=1244 ;tid=8488 ;time=10/15/2013-10:00:45.079 ;seq=1836 ;eventid=RM_ACKNOWLEDGED_COMMIT ;tx_guid=49a79b73-66c0-48cb-abb1-8b657a2e3e4d ;"TM Identifier='(null) '" ;"received acknowledgement of commit request from the resource manager #1004 for transaction enlistment #1"
pid=1244 ;tid=8488 ;time=10/15/2013-10:00:45.079 ;seq=1837 ;eventid=RM_ACKNOWLEDGED_COMMIT ;tx_guid=49a79b73-66c0-48cb-abb1-8b657a2e3e4d ;"TM Identifier='(null) '" ;"received acknowledgement of commit request from the resource manager #1004 for transaction enlistment #2"
pid=1244 ;tid=6284 ;time=10/15/2013-10:00:45.002 ;seq=1838 ;eventid=TRANSACTION_BEGUN ;tx_guid=55dd8607-c01e-4135-a247-7ef435c70bc6 ;"TM Identifier='(null) '" ;"transaction has begun, description :'<NULL>'"
pid=1244 ;tid=6284 ;time=10/15/2013-10:00:45.018 ;seq=1839 ;eventid=RM_ENLISTED_IN_TRANSACTION ;tx_guid=55dd8607-c01e-4135-a247-7ef435c70bc6 ;"TM Identifier='(null) '" ;"resource manager #1004 enlisted as transaction enlistment #1. RM guid = '7b16851c-00a5-41dd-b59c-b003dcae08ec'"
pid=1244 ;tid=6284 ;time=10/15/2013-10:00:45.018 ;seq=1840 ;eventid=RECEIVED_COMMIT_REQUEST_FROM_BEGINNER ;tx_guid=55dd8607-c01e-4135-a247-7ef435c70bc6 ;"TM Identifier='(null) '" ;"received request to commit the transaction from beginner"
pid=1244 ;tid=6284 ;time=10/15/2013-10:00:45.018 ;seq=1841 ;eventid=TRANSACTION_COMMITTED ;tx_guid=55dd8607-c01e-4135-a247-7ef435c70bc6 ;"TM Identifier='(null) '" ;"transaction has got committed"
pid=1244 ;tid=8488 ;time=10/15/2013-10:00:45.106 ;seq=1842 ;eventid=TRANSACTION_BEGUN ;tx_guid=cc4a8215-3475-4c14-b40d-d150fc79f8f7 ;"TM Identifier='(null) '" ;"transaction has begun, description :'<NULL>'"
pid=1244 ;tid=8488 ;time=10/15/2013-10:00:45.121 ;seq=1843 ;eventid=RM_ENLISTED_IN_TRANSACTION ;tx_guid=cc4a8215-3475-4c14-b40d-d150fc79f8f7 ;"TM Identifier='(null) '" ;"resource manager #1004 enlisted as transaction enlistment #1. RM guid = '7b16851c-00a5-41dd-b59c-b003dcae08ec'"
pid=1244 ;tid=8488 ;time=10/15/2013-10:00:45.121 ;seq=1844 ;eventid=RECEIVED_COMMIT_REQUEST_FROM_BEGINNER ;tx_guid=cc4a8215-3475-4c14-b40d-d150fc79f8f7 ;"TM Identifier='(null) '" ;"received request to commit the transaction from beginner"
pid=1244 ;tid=8488 ;time=10/15/2013-10:00:45.121 ;seq=1845 ;eventid=TRANSACTION_COMMITTED ;tx_guid=cc4a8215-3475-4c14-b40d-d150fc79f8f7 ;"TM Identifier='(null) '" ;"transaction has got committed"
pid=1244 ;tid=6284 ;time=10/15/2013-10:00:59.657 ;seq=1846 ;eventid=TRANSACTION_BEGUN ;tx_guid=d07cc436-033c-450b-a36c-7e2fe79cdb81 ;"TM Identifier='(null) '" ;"transaction has begun, description :'<NULL>'"
pid=1244 ;tid=6284 ;time=10/15/2013-10:00:59.657 ;seq=1847 ;eventid=RM_ENLISTED_IN_TRANSACTION ;tx_guid=d07cc436-033c-450b-a36c-7e2fe79cdb81 ;"TM Identifier='(null) '" ;"resource manager #1004 enlisted as transaction enlistment #1. RM guid = '344d3060-811c-4fc6-bab6-0eea76e3af3a'"
pid=1244 ;tid=6284 ;time=10/15/2013-10:00:59.672 ;seq=1848 ;eventid=RM_ENLISTED_IN_TRANSACTION ;tx_guid=d07cc436-033c-450b-a36c-7e2fe79cdb81 ;"TM Identifier='(null) '" ;"resource manager #1004 enlisted as transaction enlistment #2. RM guid = '7b16851c-00a5-41dd-b59c-b003dcae08ec'"
pid=1244 ;tid=6284 ;time=10/15/2013-10:00:59.672 ;seq=1849 ;eventid=RM_ENLISTED_IN_TRANSACTION ;tx_guid=d07cc436-033c-450b-a36c-7e2fe79cdb81 ;"TM Identifier='(null) '" ;"resource manager #1005 enlisted as transaction enlistment #3. RM guid = '72efe9cc-80f2-4a5b-9659-28b07987b600'"
pid=1244 ;tid=6284 ;time=10/15/2013-10:00:59.672 ;seq=1850 ;eventid=RECEIVED_ABORT_REQUEST_FROM_NON_BEGINNER ;tx_guid=d07cc436-033c-450b-a36c-7e2fe79cdb81 ;"TM Identifier='(null) '" ;"received request to abort the transaction from non beginner"
pid=1244 ;tid=6284 ;time=10/15/2013-10:00:59.672 ;seq=1851 ;eventid=TRANSACTION_ABORTING ;tx_guid=d07cc436-033c-450b-a36c-7e2fe79cdb81 ;"TM Identifier='(null) '" ;"transaction is aborting"
pid=1244 ;tid=6284 ;time=10/15/2013-10:00:59.672 ;seq=1852 ;eventid=RM_ISSUED_ABORT ;tx_guid=d07cc436-033c-450b-a36c-7e2fe79cdb81 ;"TM Identifier='(null) '" ;"abort request issued to resource manager #1004 for transaction enlistment #1"
pid=1244 ;tid=6284 ;time=10/15/2013-10:00:59.672 ;seq=1853 ;eventid=RM_ISSUED_ABORT ;tx_guid=d07cc436-033c-450b-a36c-7e2fe79cdb81 ;"TM Identifier='(null) '" ;"abort request issued to resource manager #1004 for transaction enlistment #2"
pid=1244 ;tid=6284 ;time=10/15/2013-10:00:59.672 ;seq=1854 ;eventid=RM_ISSUED_ABORT ;tx_guid=d07cc436-033c-450b-a36c-7e2fe79cdb81 ;"TM Identifier='(null) '" ;"abort request issued to resource manager #1005 for transaction enlistment #3"
pid=1244 ;tid=6284 ;time=10/15/2013-10:00:59.672 ;seq=1855 ;eventid=RM_ACKNOWLEDGED_ABORT ;tx_guid=d07cc436-033c-450b-a36c-7e2fe79cdb81 ;"TM Identifier='(null) '" ;"received acknowledgement of abort request from the resource manager #1005 for transaction enlistment #3"
pid=1244 ;tid=6284 ;time=10/15/2013-10:00:59.672 ;seq=1856 ;eventid=RM_ACKNOWLEDGED_ABORT ;tx_guid=d07cc436-033c-450b-a36c-7e2fe79cdb81 ;"TM Identifier='(null) '" ;"received acknowledgement of abort request from the resource manager #1004 for transaction enlistment #2"
pid=1244 ;tid=8488 ;time=10/15/2013-10:00:59.672 ;seq=1857 ;eventid=RM_ACKNOWLEDGED_ABORT ;tx_guid=d07cc436-033c-450b-a36c-7e2fe79cdb81 ;"TM Identifier='(null) '" ;"received acknowledgement of abort request from the resource manager #1004 for transaction enlistment #1"
pid=1244 ;tid=8488 ;time=10/15/2013-10:00:59.672 ;seq=1858 ;eventid=TRANSACTION_ABORTED ;tx_guid=d07cc436-033c-450b-a36c-7e2fe79cdb81 ;"TM Identifier='(null) '" ;"transaction has been aborted"
Run Code Online (Sandbox Code Playgroud)
I'm not sure, but it might be worth noting that there's a 14.5 second delay between the completion of the previous transaction and the start of this one. The unit tests seem to hang there, and I've yet to figure out why.
This probably doesn't matter, but the failure is in the ExecuteNonQuery below:
public IClientInternal GetClient(string clientCode)
{
string sql = "SELECT [CLIENT_CODE], [COMPANY], [EMPLOYEE] << more fields here >> FROM OPENQUERY("+
_settings.LinkedOracleServer + ", 'SELECT * FROM CLIENT WHERE "+
"CLIENT_CODE = ''" + clientCode + "'' "+
"')";
using (IDbConnection conn = DbTools.GetConnection(_configStr, _connStr, true))
{
using (IDbCommand cmd = DbTools.GetCommand(conn, "SET XACT_ABORT ON"))
{
cmd.ExecuteNonQuery();
}
using (IDbCommand cmd = DbTools.GetCommand(conn, sql))
{
DbTools.AddParameter(cmd, "@CLIENT_CODE", DbType.String, clientCode);
IDataReader reader = cmd.ExecuteReader();
if (reader.Read())
{
return ClientInternal.FromReaderRecord(reader);
}
return null;
}
}
}
Run Code Online (Sandbox Code Playgroud)
This code gets called a number of times successfully before it eventually fails.
On thing I'm wondering is, if it's possible that trasnactions aren't getting cleared out properly on the Oracle side. If I understand correctly, Oracle has a 10 distributed transaction limit. Is it possible that it thinks previous distributed transactions are still open (I see no signs fo this. All evidence seems to indicate that all the previous transactions are operating perfectly find and the DTC log shows them being committed).
Update 6: I've managed to produce the problem in a fairly small piece of code. Below, with the exception of changing the names of the DB and clientCode, is the exact code to reproduce the problem. I get a SqlException on the cmd.ExecuteReader() call in GetClients() The operation could not be performed because OLE DB provider "OraOLEDB.Oracle" for linked server "ORACLE" was unable to begin a distributed transaction. I can call GetEmployeeBadges() over and over and over again and it'll work. I can call GetClients() over and over and it'll work. But if I call GetEmployeeBadges() and then call GetClients() within a transcaction, it fails. It appears to be the result of the second call being enlisted in the transaction.
As an additional note, it appears there's something weird with the GetEmployeeBadges(). This is another oddity of our environment, but V_EMPLOYEE and V_PAEMPLOYEE are actually views on yet another Oracle database. So the Oracle server I'm hitting against has views on another Oracle server. So it's a SQL Server view of an oracle view of an oracle table. I know, it's a bit nuts. It's amazing anything here functions. If I try to run the GetEmployeeBadges() in a transaction and enlist it in a transaction, it will actually fail with: Cannot execute the query "<<query text here>>" against OLE DB provider "OraOLEDB.Oracle" for linked server "ORACLE".
I can't imagine getting this a whole lot more minimal.
class Program
{
private static string connStr = @"Server=localhost\SQLEXPRESS;Database=MYDB;Trusted_Connection=True;Enlist=false";
static void Main(string[] args)
{
GetEmployeeBadges();
using (TransactionScope ts = new TransactionScope(TransactionScopeOption.RequiresNew, new TimeSpan(0, 15, 0)))
{
GetClients();
ts.Complete();
}
}
private static void GetEmployeeBadges()
{
string sql = @"select * from OPENQUERY(ORACLE, 'select a.security_nbr, a.employee, b.last_name, b.first_name, b.department
from V_PAEMPLOYEE a, V_EMPLOYEE b
where
LENGTH(TRIM(a.SECURITY_NBR)) > 0 and
a.EMPLOYEE = b.EMPLOYEE and
a.COMPANY = 3')";
using (IDbConnection conn = DbTools.GetConnection(connStr))
{
using (IDbCommand cmd = DbTools.GetCommand(conn, "SET XACT_ABORT ON"))
{
cmd.ExecuteNonQuery();
}
using (IDbCommand cmd = DbTools.GetCommand(conn, sql))
{
cmd.CommandTimeout = 240;
IDataReader reader = cmd.ExecuteReader();
}
}
}
public static void GetClients()
{
string clientCode = "clientCode";
string sql = @"SELECT [CLIENT_CODE], [COMPANY], [EMPLOYEE], [MENU_TOKEN_CODE], [ADMINISTRATOR_FLAG], [SUPERVISOR_FLAG],
[CLIENT_DESCR], [DEFAULT_QUEUE_CODE], [FG_WHSE_CODE], [FRT_WHSE_CODE], [BILL_COMP_CODE], [FI_COMP_CODE],
[DEFAULT_ROLE], [DEFAULT_PRINTER_CODE], [SHIP_PRINTER_CODE], [DEFAULT_DISPLAY]
FROM OPENQUERY( ORACLE, 'SELECT * FROM CLIENT WHERE CLIENT_CODE = ''clientCode''')";
using (IDbConnection conn = DbTools.GetConnection(connStr, true))
{
using (IDbCommand cmd = DbTools.GetCommand(conn, "SET XACT_ABORT ON"))
{
cmd.ExecuteNonQuery();
}
using (IDbCommand cmd = DbTools.GetCommand(conn, sql))
{
DbTools.AddParameter(cmd, "@CLIENT_CODE", DbType.String, clientCode);
IDataReader reader = cmd.ExecuteReader();
reader.Read();
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
The DbTools stuff, in case it's helpful is:
public static class DbTools
{
public static IDbConnection GetConnection(string connectionString)
{
return GetConnection(connectionString, false);
}
public static IDbConnection GetConnection(string connectionString, bool enlistTransaction)
{
SqlConnection conn = new SqlConnection(connectionString);
conn.Open();
if (enlistTransaction && Transaction.Current != null)
{
conn.EnlistTransaction(Transaction.Current);
}
return conn;
}
public static IDbCommand GetCommand(IDbConnection conn, string command)
{
IDbCommand cmd = conn.CreateCommand();
cmd.CommandText = command;
return cmd;
}
public static IDbDataParameter AddParameter(IDbCommand cmd, string name, DbType type, object value)
{
IDbDataParameter param = cmd.CreateParameter();
param.ParameterName = name;
param.DbType = type;
param.Value = value != null ? value : DBNull.Value;
cmd.Parameters.Add(param);
return param;
}
}
Run Code Online (Sandbox Code Playgroud)
Just 23 hours left on the bounty. I'd LOVE to give that 150 points to someone!!!
这个问题是由我们非常奇怪的设置引起的。
我们有一个 SQL Server,它有一个链接的 Oracle 服务器。我们在 SQL Server 中为 Oracle 服务器上的表创建视图。Oracle 服务器中的一些视图是另一个 Oracle 服务器中表的视图。我们只是在服务器 2 中的 Oracle 表上的服务器 1 中的 Oracle 视图的 SQL Server 中创建视图。即使我们在从视图的视图中获取数据时没有使用事务,也会导致后续执行中的事务失败(如果有人愿意评论这是如何可能的,我希望得到解释。)
我们的解决方案是简单地创建第二个链接服务器并绕过视图的视图。您可能想知道为什么我们一开始不这样做,这只是因为,在我们遇到这个问题之前,没有令人信服的理由拥有第二个链接服务器(并且第二个服务器有非常敏感的信息,所以我们有点喜欢最小化访问它的路径的想法)。显然我们现在有一个令人信服的理由。
虽然我没有给出 Exth3 的答案,但我确实给了他/她奖励积分,因为他/她提供了最终导致我发现问题的信息。谢谢Exth3!
| 归档时间: |
|
| 查看次数: |
2543 次 |
| 最近记录: |