.net中的事务处理(二)
点击次数:13 次 发布日期:2008-11-26 23:34:15 作者:源代码网
|
源代码网推荐 The .NET Framework supports MSMQ transactions in two different ways: manually (internally) by allowing multiple messages to be sent or received as part of a transaction and automatically (externally) by participating in Distributed Transaction Coordinator (DTC) transactions. 源代码网推荐 源代码网推荐 MSMQ manual transactions are supported through the MessageQueueTransaction class and are handled entirely inside the MSMQ engine. Please refer to Duncan Mackenzie"s article, Reliable Messaging with MSMQ and .NET, for details. 源代码网推荐 源代码网推荐 Automatic Transactions 源代码网推荐 The .NET Framework relies on MTS/COM+ services to support automatic transactions. COM+ uses the Microsoft Distributed Transaction Coordinator (DTC) as a transaction manager and a transaction coordinator to run transactions in a distributed environment. This enables a .NET application to run a transaction that combines diverse activities across multiple resources such as inserting an order into a SQL Server database, writing a message to a Microsoft Message Queue (MSMQ) queue, sending an e-mail message, and retrieving data from an Oracle database. 源代码网推荐 源代码网推荐 By providing a programming model based on declarative transactions, COM+ makes it very simple for your application to run transactions that span heterogeneous resources. The caveat is that it pays a performance penalty due to DTC and COM interoperability overhead and there is no support for nested transactions. 源代码网推荐 源代码网推荐 ASP.NET pages, Web Service methods, and .NET classes can be marked to be transactional by setting a declarative transaction attribute. 源代码网推荐 源代码网推荐 ASP.NET 源代码网推荐 <@ Page Transaction="Required"> 源代码网推荐 源代码网推荐 ASP.NET Web Service 源代码网推荐 <%@ WebService Language="VB" Class="Class1" %> 源代码网推荐 <%@ assembly name="System.EnterpriseServices" %> 源代码网推荐 … 源代码网推荐 Public Class Class1 源代码网推荐 Inherits WebService 源代码网推荐 <WebMethod(TransactionOption := TransactionOption.RequiresNew)> _ 源代码网推荐 Public Function Method1() 源代码网推荐 … 源代码网推荐 源代码网推荐 To participate in automatic transactions, a .NET class must be inherited from the System.EnterpriseServices.ServicedComponent class, which enables it to run inside COM+. When you do this, COM+ interacts with the DTC to create a distributed transaction and also enlists all resource connections behind the scenes. You also need to set a declarative transaction attribute on the class to determine its transactional behavior. 源代码网推荐 源代码网推荐 Visual Basic .NET 源代码网推荐 源代码网推荐 <Transaction(TransactionOption.Required)> Public Class Class1 源代码网推荐 Inherits ServicedComponent 源代码网推荐 源代码网推荐 Visual C# .NET 源代码网推荐 源代码网推荐 [Transaction(TransactionOption.Required)] 源代码网推荐 public class Class1 : ServicedComponent { 源代码网推荐 … 源代码网推荐 } 源代码网推荐 源代码网推荐 The transaction attribute for a class can be set to any of the following options: 源代码网推荐 源代码网推荐 Disabled—indicates that the object is never created in a COM+ transaction. The object can directly use DTC for transactional support. 源代码网推荐 NotSupported—indicates that the object is never created in a transaction. 源代码网推荐 Supported—indicates that the object runs in the context of its creator"s transaction. If the object is the root object itself or its creator is not running in a transaction, the object is created without a transaction. 源代码网推荐 Required—indicates that the object runs in the context of its creator"s transaction. If the object is the root object itself or its creator is not running in a transaction, the object is created with a new transaction. 源代码网推荐 RequiresNew—indicates that the object requires a transaction and the object is created with a new transaction. 源代码网推荐 The following code shows a .NET class configured to run within COM+, with assembly attributes set to configure the COM+ application properties. 源代码网推荐 源代码网推荐 Visual Basic .NET 源代码网推荐 源代码网推荐 Imports System 源代码网推荐 Imports System.Runtime.CompilerServices 源代码网推荐 Imports System.EnterpriseServices 源代码网推荐 Imports System.Reflection 源代码网推荐 源代码网推荐 "Registration details. 源代码网推荐 "COM+ application name as it appears in the COM+ catalog 源代码网推荐 <Assembly: ApplicationName("Class1")> 源代码网推荐 "Strong name for assembly 源代码网推荐 <Assembly: AssemblyKeyFileAttribute("class1.snk")> 源代码网推荐 <Assembly: ApplicationActivation(ActivationOption.Server)> 源代码网推荐 源代码网推荐 <Transaction(TransactionOption.Required)> Public Class Class1 源代码网推荐 Inherits ServicedComponent 源代码网推荐 Public Sub Example1() 源代码网推荐 … 源代码网推荐 End Sub 源代码网推荐 End Class 源代码网推荐 源代码网推荐 Visual C# .NET 源代码网推荐 源代码网推荐 using System; 源代码网推荐 using System.Runtime.CompilerServices; 源代码网推荐 using System.EnterpriseServices; 源代码网推荐 using System.Reflection; 源代码网推荐 源代码网推荐 //Registration details. 源代码网推荐 //COM+ application name as it appears in the COM+ catalog 源代码网推荐 [Assembly: ApplicationName("Class1")] 源代码网推荐 "Strong name for assembly 源代码网推荐 [Assembly: AssemblyKeyFileAttribute("class1.snk")] 源代码网推荐 [Assembly: ApplicationActivation(ActivationOption.Server)] 源代码网推荐 源代码网推荐 [Transaction(TransactionOption.Required)] 源代码网推荐 public class Class1 : ServicedComponent { 源代码网推荐 [AutoComplete] 源代码网推荐 public void Example1() 源代码网推荐 { 源代码网推荐 … 源代码网推荐 } 源代码网推荐 } 源代码网推荐 源代码网推荐 <Assembly: ApplicationName("Class1")> specifies the name of the COM+ application to install the components of the assembly into. <Assembly: ApplicationActivation(ActivationOption.Server)> specifies if the COM+ application is a server or library application. The assembly must be installed into the global assembly cache (GAC) using the gacutil command-line tool (GacUtil.exe) when you specify ApplicationActivation(ActivationOption.Server). 源代码网推荐 源代码网推荐 You can use the Regsvcs.exe command-line tool to convert the assembly to a type library, and register and install the type library into the specified COM+ application. The tool also configures properties that you have added programmatically to your assembly. For example, if ApplicationActivation(ActivationOption.Server) is specified in the assembly, the tool will create a server application. If an assembly is invoked without being installed with COM+, the run time creates and registers a type library and installs it with COM+. You can see and configure the COM+ application created for your assembly in the Component Services snap-in. 源代码网推荐 源代码网推荐 The process to create, register, and use serviced components is covered in detail in Writing Serviced Components in the .NET Framework Developer"s Guide. 源代码网推荐 源代码网推荐 The following code fragment shows a transactional class configured to run under COM+, which executes two SQL commands within the boundary of a transaction. The first command inserts the order header of an order into the Orders table and returns the OrderId of the newly inserted order, which is used by the second command to insert the detail of the same order into the OrderDetails table. The transaction is aborted if either of the two commands fails to execute thereby preventing the rows from being added to the database. 源代码网推荐 源代码网推荐 Visual Basic .NET 源代码网推荐 源代码网推荐 <Transaction(TransactionOption.Required)> Public Class Class1 源代码网推荐 Inherits ServicedComponent 源代码网推荐 源代码网推荐 Public Sub Example1() 源代码网推荐 … 源代码网推荐 Try 源代码网推荐 " Create a New Connection 源代码网推荐 conn = New SqlConnection("ConnString") 源代码网推荐 " Open the Connection 源代码网推荐 conn.Open() 源代码网推荐 " Create a new Command object 源代码网推荐 cmd = New SqlCommand() 源代码网推荐 " Insert the Order header 源代码网推荐 " Set the Command properties 源代码网推荐 With cmd1 源代码网推荐 .CommandType = CommandType.StoredProcedure 源代码网推荐 .CommandText = "InsertOrderHeader" 源代码网推荐 .Connection = conn 源代码网推荐 " Add input and output parameters 源代码网推荐 .Parameters.Add("@CustomerId", SqlDbType.Int) 源代码网推荐 … 源代码网推荐 .ExecuteNonQuery() 源代码网推荐 " Clear the parameters for the next command 源代码网推荐 .Parameters.clear() 源代码网推荐 End With 源代码网推荐 源代码网推荐 " Insert all the Order details 源代码网推荐 " Set Command properties 源代码网推荐 With cmd 源代码网推荐 .CommandType = CommandType.StoredProcedure 源代码网推荐 .CommandText = "InsertOrderDetail" 源代码网推荐 .Connection = conn 源代码网推荐 " Add parameters 源代码网推荐 .Parameters.Add("@OrderId", SqlDbType.Int) 源代码网推荐 … 源代码网推荐 " Execute the command 源代码网推荐 .ExecuteNonQuery() 源代码网推荐 " Repeat the above few lines for each order 源代码网推荐 detail 源代码网推荐 End With 源代码网推荐 源代码网推荐 " Commit the Transaction 源代码网推荐 ContextUtil.SetComplete() 源代码网推荐 Catch 源代码网推荐 " Rollback the Transaction 源代码网推荐 ContextUtil.SetAbort() 源代码网推荐 Finally 源代码网推荐 " Cleanup Code 源代码网推荐 End Try 源代码网推荐 End Sub 源代码网推荐 源代码网推荐 Using the System.EnterpriseServices.ContextUtil class, you can obtain information about the COM+ object context. It exposes SetComplete and SetAbort methods to explicitly commit and rollback a transaction respectively. As you might expect, the ContextUtil.SetComplete method is called at the very end of the try block when all the operations have been executed successfully to commit the transaction. Any exception thrown is caught in the catch block where the transaction is aborted using ContextUtil.SetAbort. 源代码网推荐 源代码网推荐 You can also cause a serviced component to automatically vote to commit or abort the transaction using the System.EnterpriseServices.AutoComplete attribute class. The component votes in favor of committing the transaction if the method call returns successfully. If the method call throws an exception, the transaction is aborted automatically; you don"t need to explicitly call ContextUtilSetAbort. To use this feature, insert the <AutoComplete> attribute before the class method: 源代码网推荐 源代码网推荐 Visual Basic .NET 源代码网推荐 源代码网推荐 <Transaction(TransactionOption.Required)> Public Class Class1 源代码网推荐 Inherits ServicedComponent 源代码网推荐 <AutoComplete()> Public Sub Example1() 源代码网推荐 … 源代码网推荐 End Sub 源代码网推荐 End Class 源代码网推荐 源代码网推荐 Visual C# .NET 源代码网推荐 源代码网推荐 [Transaction(TransactionOption.Required)] 源代码网推荐 public class Class1 : ServicedComponent { 源代码网推荐 [AutoComplete] 源代码网推荐 public void Example1() 源代码网推荐 { 源代码网推荐 … 源代码网推荐 } 源代码网推荐 } 源代码网推荐 源代码网推荐 The <AutoComplete> attribute offers the easiest way to do transactional programming by allowing you to avoid having to explicitly commit or rollback transactions. You get the exact same functionality the previous example where we explicitly called ContextUtil.SetAbort in the catch block to abort the transaction. The disadvantage is that it is not obvious that transactions are involved at all and may be forgotten when maintaining the code at a later time. Also, it does not allow you to throw a user-friendly message in case you want to when a transaction fails. In such cases you should explicitly catch any exceptions, call ContextUtil.SetAbort, and throw the custom message. 源代码网推荐 源代码网推荐 In systems that need transactions to run across MSMQ and other transaction-aware resources such as a SQL Server database, there is no choice but to use DTC or COM+ transactions. DTC coordinates all the resource managers participating in a distributed transaction and also manages activities related to the transaction. Please refer to Duncan Mackenzie"s article, Reliable Messaging with MSMQ and .NET, for an example of distributed transaction spanning MSMQ and SQL Server. 源代码网推荐 源代码网推荐 Conclusion 源代码网推荐 Each transaction technique offers trade-offs with respect to application performance and code maintainability. Running a database transaction implemented in a stored procedure offers the best performance as it needs only a single round trip to the database. It also gives the flexibility of explicitly controlling the transaction boundary. Although it provides good performance and flexibility, you need to code in Transact SQL, which is not as easy to code as in .NET. 源代码网推荐 源代码网推荐 Manual transactions using ADO.NET transaction objects are easy to code and give you the flexibility of controlling the transaction boundary with explicit instructions to begin and end the transaction. The trade off for this ease and flexibility is that it incurs a performance cost for extra round trips to the database to complete the transaction. 源代码网推荐 源代码网推荐 An automatic transaction will be the only choice if your transaction spans multiple transaction aware resource managers which could include SQL Server databases, MSMQ Message Queues, etc. It greatly simplifies the application design and reduces coding requirements. However, since COM+ service does all the coordination work, it may have some extra overhead. 源代码网推荐 源代码网推荐 源代码网推荐 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnbda/html/Bdadotnettransact1.asp?frame=true 源代码网推荐 源代码网推荐 源代码网供稿. |
