816141 HOW TO:在 Visual C# .NET 组件中使用 COM+ 事务处理 (From MKBA)

有关本文的 Microsoft Visual Basic .NET 版本,请参阅 315707.

本任务的内容

概要

本文分步介绍了如何在 Visual C# .NET 类中使用 COM+(组件服务)事务处理。一组数据库操作被视为一个事务单元。要么所有的操作都成功;要么如果其中一个操作失败,则整个事务处理失败。对于后一种情况,所尝试的任何数据库操作都不会发布到基础数据库中。

返回页首

要求

下面几项介绍了推荐使用的硬件、软件、网络设施、技能和知识以及必需的 Service Pack:
  • Microsoft Windows 2000 Server SP1
  • Microsoft Internet 信息服务 (IIS) 4.0 或更高版本
  • Microsoft Internet Explorer 5.0、5.5 或 6.0
本文假定您已熟悉以下主题:
  • 事务的概念和处理
  • COM+(组件服务)
返回页首

COM+ 事务处理服务

您可以使用 Microsoft .NET Framework 中的 System.EnterpriseServices 命名空间来实现事务处理。要访问 COM+ 事务处理服务,需创建一个类。为此,请按照下列步骤操作:
  1. 启动 Visual Studio .NET。
  2. 在“文件”菜单上,指向“新建”,然后单击“项目”。
  3. 单击“项目类型”下的“Visual C# 项目”,然后单击“模板”下的“类库”。将该项目命名为 prjEnterprise
  4. 默认情况下将创建 Class1。
  5. 在解决方案资源管理器中,右键单击“引用”,然后单击“添加引用”。
  6. “添加引用”对话框将出现。在“.NET”选项卡的“组件名称”下,双击“System.EnterpriseServices”。
  7. 确保“System.EnterpriseServices”显示在“选定的组件”下。单击“确定”。
  8. 将以下代码添加到 Class1.cs 文件中的任何其他语句之前:
    using System.EnterpriseServices;
    using System.Data.SqlClient;
  9. 向 Class1.cs 文件中添加一个名为 clsES 的新类。
  10. 要使用 COM+ 事务处理服务,您的类 (clsES) 必须按如下方式从 ServicedComponent 继承功能:
    public class clsES : ServicedComponent
  11. 按如下方式使用一个 Transaction 属性来指定该类的事务支持级别:
    [Transaction(TransactionOption.Required)]public class clsES : ServicedComponent
  12. clsES 类中创建一个方法,然后将其命名为 dbAccess,该方法接收四个整数作为输入参数。前两个参数提供一个产品 ID 和这种产品的订货数量;后两个参数提供一个产品 ID 和这种产品的库存数量。该方法对这些指定的产品 ID 执行一组数据库操作,这组数据库操作将被视为一个事务。
    void dbAccess(int pID1,int onOrder, int pID2, int inStock)
  13. dbAccess 方法中,创建一个用于 Northwind 数据库的 SQL 连接对象,然后打开该连接。数据库操作是使用以下数据库进行的:

    注意 不要忘记更改下面的连接字符串参数以反映您的 SQL Server 服务器的正确值。
    SqlConnection Conn = new SqlConnection("user id=<username>;password=<strong password>;Initial Catalog=northwind;Data Source=2E124//SQL;");				Conn.Open();
  14. 设置一个 try 块以捕获在数据库处理过程中可能出现的任何异常。您必须捕获这些异常来终止事务。try 块包括两个数据库操作,每个操作更新指定的 Products 表记录中的一个不同字段。
     try { 
    
  15. 对 Products 表执行第一个更新。按照前两个输入参数的指定,使用 onOrder 值更新具有指定 ID 的产品的 UnitsonOrder 字段。使用下面的 SQL 命令运行这个 SQL 更新:
    SqlCommand sqlCommand = new SqlCommand("UPDATE myProducts SET UnitsonOrder = " + onOrder + " WHERE productID = " + pID1, Conn);
    				sqlCommand.ExecuteNonQuery();
  16. 对 Products 表执行另一个更新。按照第三个和第四个输入参数的指定,使用 inStock 值更新具有指定 ID 的产品的 UnitsinStock 字段。使用下面的 SQL 命令运行这个 SQL 更新:
    sqlCommand.CommandText = "UPDATE myProducts SET UnitsinStock = " + inStock + " WHERE productID = " + pID2;
    				sqlCommand.ExecuteNonQuery();
    
  17. 因为这些更新是 COM+ 事务处理的一部分,所以它们作为一个单元提交。如果没有引发错误,将使用 System.EnterpriseServices 命名空间中的 contextUtil 类的 setComplete 方法提交该事务(在本例中是两个更新):
    ContextUtil.SetComplete();
  18. 与 Northwind 数据库的连接关闭:
    Conn.Close();
    }
  19. 您必须捕获运行 SQL 命令时发生的任何异常以便您能够终止整个事务:
    catch(Exception e){ 
  20. 使用 System.EnterpriseServices 命名空间中的 contextUtil 类的 setAbort 方法来终止整个事务。如果第一个更新成功但第二个更新失败,则两个更新都不会发布到 Products 表。捕获到的异常将抛给调用者,表明事务处理已失败:
    ContextUtil.SetAbort();
    				throw e;
    }
  21. 为使该组件正确运行,该组件必须有一个强名称。生成一个强名称,然后使用该强名称对程序集进行签名。为此,请按照下列步骤操作:
    1. 在 Visual Studio .NET 命令提示符下,键入 sn.exe -k snEnterprise.snk 以创建一个密钥文件。有关使用强名称对程序集进行签名的更多信息,请参阅 .NET Framework SDK 文档。
    2. 将 nEnterprise.snk 复制到您的项目文件夹中。
    3. 在 AssemblyInfo.vc 中,将以下代码添加到其他程序集属性语句之前或之后:
      [assembly: AssemblyKeyFileAttribute("..//..//snEnterprise.snk")]		
    4. 进行保存,然后生成您的项目。
返回页首

完整代码列表



注意 不要忘记更改下面的连接字符串参数以反映您的 SQL Server 服务器的正确值。
using System;
using System.Data;
using System.Data.SqlTypes;
using System.Data.Common;
using System.EnterpriseServices;
using System.Data.SqlClient;

namespace prjEnterprise
{
	
	[Transaction(TransactionOption.Required)]public class clsES:ServicedComponent
	{
		public SqlConnection Conn;

		public void dbAccess(int pID1, int onOrder, int pID2, int inStock)
		{
			try
			{			
				SqlConnection Conn = new SqlConnection("user id=<username>;password=<strong password>;Initial Catalog=northwind;Data Source=2E124//SQL;");
				Conn.Open();
				
SqlCommand sqlCommand = new SqlCommand("UPDATE myProducts SET UnitsonOrder = " + onOrder + " WHERE productID = " + pID1, Conn);
				sqlCommand.ExecuteNonQuery();
				
				sqlCommand.CommandText = "UPDATE myProducts SET UnitsinStock = " + inStock + " WHERE productID = " + pID2;
				sqlCommand.ExecuteNonQuery();

				ContextUtil.SetComplete();
				Conn.Close();
			}
			catch(Exception e)
			{
				ContextUtil.SetAbort();
			
				throw e;
			}
			finally
			{

			}
		}
	}	
}

返回页首

确认它可以使用

要测试这个代码,需要创建一个使用 clsES 项目的控制台应用程序。一种情形是:事务处理成功,指定产品的 onorderinstock 字段得到了更新。另一种情形是:对一个指定产品的 onOrder 字段的更新成功了,但对另一个指定产品的 inStock 字段的更新失败了(因为在 Products 表中不存在指定的产品编号)。这会导致事务失败,该事务将被忽略。
  1. 在 Visual Studio .NET 中,指向“文件”菜单上的“新建”,然后单击“项目”。
  2. 单击“项目类型”下的“Visual C# 项目”,然后单击“模板”下的“控制台应用程序”。
  3. 在“名称”文本框中,键入 testES。确保已选中了“添入解决方案”选项。
  4. 单击“确定”将该项目添加到解决方案中。
  5. 要使 testES 测试 clsES,您必须添加一个引用。在解决方案管理器中,右键单击 testES(您刚才添加的)下的“引用”,然后单击“添加引用”。
  6. 此时出现“添加引用”对话框。在“项目”选项卡中,双击“prjEnterprise”。
  7. 在“选定的组件”下显示一个引用。单击“确定”添加对该项目的引用。
  8. 在项目中添加对 System.EnterpriseServices 库的引用。在解决方案资源管理器中,右键单击“引用”,然后单击“添加引用”。
  9. “添加引用”对话框将出现。在“.NET”选项卡的“组件名称”下,双击“System.EnterpriseServices”。
  10. 确保“System.EnterpriseServices”显示在“选定的组件”下。单击“确定”。
  11. 右键单击控制台应用程序(testES),然后单击“设为启动项目”。
  12. 将以下源代码粘贴到 Class1 类的 Main 函数中:
    	prjEnterprise.clsES myTest = new prjEnterprise.clsES();
    
    				try 
    				{
    					myTest.dbAccess(1, 777, 2, 888);
    					Console.WriteLine("TRANSACTION ONE -- SUCCESS");
    
    					myTest.dbAccess(1, 5, 2, -20);
    					Console.WriteLine("TRANSACTION TWO -- SUCCESS");
    				}
    				catch (Exception e)
    				{
    					Console.WriteLine("TRANSACTION FAILURE");
    				}
  13. 按 F5 键以运行测试代码。

    在代码的第 7 步中,对 dbAccess 的第一个调用成功完成。产品 1 和产品 2 均在 Products 表中。产品 1 的 onOrder 字段更新为 777,产品 2 的 inStock 字段更新为 888。因为这个事务处理成功完成,所以您将在输出窗口中收到以下消息
    TRANSACTION ONE - SUCCESS


    dbAccess 的第二个调用失败。因此,不会将 dbAccess 中的对 Products 表的任何更新语句发布到数据库。虽然产品 1 本来可以将它的 onOrder 字段更新为 5,但是产品 2 不能将它的 inStock 字段设为 -20(因为 Products 表定义中定义的一个约束条件规定 inStock 不允许取负数值)。

    因此,对 dbAccess 的这个调用失败了,从而整个事务操作也随之失败。Products 表将保持调用 dbAccess 之前的状态。catch 语句处理来自 dbAccess 的事务处理失败通知,您将在输出窗口中收到以下错误信息:
    TRANSACTION FAILURE
  14. 使用 SQL Server 企业管理器检查 Northwind 的 Products 表的内容。查看产品 1,onOrder 字段的值为 777。查看产品 2,instock 字段的值为 888。由此可见,对 dbAccess 的第二个调用(此调用本会使这些字段具有不同的值)失败了。
返回页首

疑难解答

  • 确保使用 COM+ 服务的所有项目都有一个强名称。
  • 使用 COM+ 服务的所有类都必须继承服务组件。服务组件位于 System.EnterpriseServices 命名空间中。
  • 进行调试时,事务在提交或终止前可能会超时。要避免出现超时,请在事务属性中使用一个超时属性。在下面的示例中,在完成任何事务时,关联的方法在超时前都有 1,200 秒的执行时间。
    [Transaction(TransactionOption.Required,timeout:=1200)]
返回页首

参考

有关其他信息,请访问下面的 Microsoft Developer Network (MSDN) Web 站点:

COM+ 集成:.NET Enterprise Services 如何帮助您生成分布式应用程序
http://msdn.microsoft.com/msdnmag/issues/01/10/complus/default.aspx

服务组件:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/f_and_m/html/vxconInterop.asp

返回页首

这篇文章中的信息适用于:

  • Microsoft Visual C# .NET (2003)
  • Microsoft Visual C# .NET (2002)
最近更新:2003-12-23 (2.0)
关键字:kbcomplusobj kbSQLProg kbSqlClient kbDatabase kbHOWTOmaster KB816141 kbAudDeveloper
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值