[英]SQL Server and WCF Transactions across Linked Oracle Servers
注意请参阅更新6.它有一个简单的应用程序,演示如何重新创建问题。
我是DTC的噩梦......我们的设置是我们有两个数据库; 一个SQL Server 2008数据库和一个Oracle数据库(11g,我相信)。 我已经安装了oracle MTS的东西。 我将DTC配置为允许分布式事务。 对Oracle表的所有访问都通过SQL Server数据库中与链接服务器中的Oracle表相对的视图进行。
(关于DTC配置:选中 - >网络DTC访问,允许远程客户端,允许入站,允许出站,相互身份验证(尝试所有3个选项),启用XA事务和启用SNA LU 6.2事务.DTC以NT AUTHORITY\\NetworkService
登录NT AUTHORITY\\NetworkService
)
我们的应用程序是一个ASP.NET MVC 4.0应用程序,它调用许多WCF服务来执行数据库工作。 目前,Web应用程序和WCF服务共享相同的应用程序池(不确定它是否相关,但以防万一...)
我们的一些服务是交易性的,有些则不是。
事务性的每个WCF服务在其接口上都具有以下属性:
[ServiceContract(SessionMode=SessionMode.Required)]
以及界面中方法签名的以下属性:
[TransactionFlow(TransactionFlowOption.Allowed)]
以及每个方法实现的以下属性:
[OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
在我的数据访问层中,所有事务方法都设置如下:
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 ...
}
}
作为事务性调用事务DAL代码的服务。 我们的想法是将需要交易的东西(少数情况)与不需要交易的东西(约95%的情况)分开。
不应该在事务中调用事务性和非事务性WCF方法(尽管我没有验证这一点,这可能是我遇到问题的原因。我不确定,这是我为什么的一部分'我问这里。)
正如我之前提到的,在大多数情况下,这一切都很好。
我不知道是什么时候启动它,我开始得到错误。 一旦他们开始,几乎一切都开始失败了一段时间。 最终事情又开始了。 不知道为什么......这都是在一个用户的测试环境中。
有时错误是:
无法为链接服务器“ORACLSERVERNAME”的OLE DB提供程序“OraOLEDB.Oracle”启动嵌套事务。 由于XACT_ABORT选项设置为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
这让我想知道是否有什么东西可能会让交易在某个地方开放? 我觉得有一种感觉,因为缺乏更好的术语,“悬空交易”没有得到承诺或回滚。 在我使用TransactionScope的每种情况下,它都发生在“使用”语句中,所以一切都应该回滚或提交。 但我真的开始认为某种程度上有些东西在泄漏...
更新4:与更新3相关。我正在执行手动登记。 我们的连接字符串有“Enlist = false”。 DBTools.GetConnection()
接受一个布尔参数,该参数指定是否将当前事务登记到连接中。 我发布此更新是因为,基于Update 3中的内容,我想知道,或许,不应该招募交易的连接是否以某种方式招募它们。
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;
}
更新5:我设法找到一组单元测试,如果我运行该组,它总是在同一个测试中的同一个地方失败(但如果我只是自己运行该测试,一遍又一遍,它不会不会失败。它与之前运行的测试有关。)我设法获得了一些DTC跟踪日志。 这是一个显示初始失败事务的日志。 我也在展示一些先前的交易,以防看到一些有意义的交易有所帮助。 失败的交易从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"
我不确定,但值得注意的是,在上一次交易完成和这次交易开始之间有14.5秒的延迟。 单元测试似乎挂在那里,我还没弄清楚原因。
这可能无关紧要,但失败在下面的ExecuteNonQuery中:
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;
}
}
}
在最终失败之前,此代码会成功调用多次。
我想知道的是,如果有可能在Oracle方面没有正确清除trasnactions。 如果我理解正确,Oracle有10个分布式事务限制。 它是否有可能认为以前的分布式交易仍然是开放的(我没有看到任何迹象。所有证据似乎都表明所有以前的交易都在完美运行,而DTC日志显示它们已被提交)。
更新6:我设法用相当小的代码产生问题。 下面,除了更改DB和clientCode的名称之外,是重现问题的确切代码。 我得到一个SqlException
上cmd.ExecuteReader()
的调用GetClients()
The operation could not be performed because OLE DB provider "OraOLEDB.Oracle" for linked server "ORACLE" was unable to begin a distributed transaction.
我可以GetEmployeeBadges()
调用GetEmployeeBadges()
,它会起作用。 我可以一遍又一遍地调用GetClients()
,它会工作。 但是,如果我调用GetEmployeeBadges()然后在transcaction中调用GetClients()
,它将失败。 它似乎是在交易中登记第二个电话的结果。
另外需要注意的是, GetEmployeeBadges()
似乎有些奇怪。 这是我们环境的另一个奇怪之处,但V_EMPLOYEE和V_PAEMPLOYEE实际上是另一个Oracle数据库的视图。 所以我遇到的Oracle服务器在另一台Oracle服务器上有视图。 所以这是一个oracle表的oracle视图的SQL Server视图。 我知道,这有点疯狂。 这里的任何功能都令人惊叹。 如果我尝试在事务中运行GetEmployeeBadges()
并在事务中登记它,它实际上将失败: Cannot execute the query "<<query text here>>" against OLE DB provider "OraOLEDB.Oracle" for linked server "ORACLE".
我无法想象这会让这一点变得更小。
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();
}
}
}
}
DbTools的东西,万一它有用的是:
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;
}
}
奖金还剩23个小时。 我愿意给那150分给那个人!!!
根据KB187289 ,Oracle不支持嵌套事务,因此只要事务在没有干净回滚的情况下中止,就会出现第一条错误消息。 在这种情况下,数据库都不能完成事务,并且将停止,直到阻止事务被丢弃。
XACT_ABORT
强制事务在第一个运行时错误时终止并执行立即回滚。 为所有连接激活XACT_ABORT
以便立即抛出运行时错误,其中一个可能导致事务在任一数据库上失败。
如果没有XACT_ABORT
,MS SQL服务器会尝试在嵌套事务中对已损坏的查询进行静默,部分回滚。 运行时错误将被抑制,除非明确捕获,否则将被忽略。
这不能解决您的原始问题(仍然存在失败的事务),但它使您能够首先看到运行时错误。
TRY...CATCH
和嵌套事务将是自SQL 2005以来执行正确错误处理的更简洁方法,但由于Oracle不支持这些语言扩展,因此不适合您。
这个问题是由我们非常奇怪的设置引起的。
我们有一个具有链接Oracle服务器的SQL Server。 我们在SQL Server中为Oracle服务器上的表创建视图。 Oracle服务器中有一些视图是对另一个Oracle服务器中的表的视图。 我们只是在服务器2中的Oracle表上的服务器1中的Oracle视图的SQL服务器中创建视图。即使我们在从视图的视图中获取数据时没有使用事务,也导致后续执行中的事务失败(如果有人关心如何做到这一点,我会喜欢解释。)
我们的解决方案是简单地创建第二个链接服务器并绕过视图的视图。 你可能想知道我们为什么不开始这样做,这只是因为,直到我们遇到这个问题,没有令人信服的理由有第二个链接服务器(并且第二个服务器上有非常敏感的信息,所以我们喜欢最小化访问它的路径的想法)。 显然,我们现在有一个令人信服的理由。
虽然我没有给出Exth3的答案,但我确实给了他/她提供最终导致我发现问题的信息的赏金点。 谢谢Exth3!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.