如何使用 Visual c + +.net 组件中或在 Visual c + + 2005年组件使用 COM + 事务

文章翻译 文章翻译
文章编号: 815814 - 查看本文应用于的产品
展开全部 | 关闭全部

本文内容

摘要

本分步指南介绍了如何使用 COM + (组件服务) 在 Microsoft Visual c + +.net 类中或在 Microsoft Visual c + + 2005年类中的交易记录。一组数据库操作被视为一个单元。所有操作都成功或如果将失败一次操作整个事务将失败。在后一种情况下而尝试任何数据库操作无法过帐到基础数据库。

要求

本文假定您熟悉下列主题:
  • 事务的概念和处理
  • COM + (组件服务)

COM + 事务服务

您可以实现事务处理与在 Microsoft.net 框架中 System.EnterpriseServices 命名空间。要访问 COM + 事务的服务创建一个类。若要这样做,请按照下列步骤操作:
  1. 启动 Visual Studio.net 或 Visual Studio 2005。
  2. 文件 菜单上指向 新建,然后单击 项目
  3. 项目类型 框中,单击 Visual c + + 项目,然后单击 模板 下的 类库 (.NET)。名称项目 prjEnterprise。

    注意在 Visual 有关 Studio 的 2005 年在 项目类型 框中,单击 Visual c + +,然后单击在 模板 下的 类库
  4. 在解决方案资源管理器中,右击 引用,然后单击 添加引用
  5. 单击 添加引用 对话框中的 NET 选项卡。
  6. 双击 组件名称 下的 System.EnterpriseServices
  7. 请确保 System.EnterpriseServices 显示在 选定的组件,下,然后单击 确定
  8. 将下面的代码在任何其他语句之前添加 prjEnterprise.h 文件中:
    using namespace System;
    using namespace System::Data;
    using namespace System::Data::SqlTypes;
    using namespace System::Data::Common;
    using namespace System::EnterpriseServices;
    using namespace System::Data::SqlClient;
    
  9. 添加新的类名为 clsES prjEnterprise.h 文件。
  10. 若要将 COM + 事务服务确保您的类 (clsES) 功能从 ServicedComponent 类继承,如下所示:
    public __gc class clsES:public ServicedComponent
    
  11. 使用 事务 属性来指定的事务处理支持的类级别,如下所示:
    [Transaction(TransactionOption::Required,Timeout=5)]public __gc class clsES:public ServicedComponent
    
  12. 在收到四个输入的整数参数的 clsES 类中创建一个方法。命名类 dbAccess。前两个参数提供该产品的订单上一个产品 ID 和单位。两个参数为该产品提供一个产品 ID 和库存单位。此方法执行的一组数据库操作,对要被视为一个事务的这些指定的产品 id:
    public:	void dbAccess(int pID1, int onOrder, int pID2, int inStock)
  13. dbAccess 方法中创建 SQL 连接对象的罗斯文数据库,然后打开该连接。通过使用以下数据库执行数据库操作:
    SqlConnection * Conn = new SqlConnection("user id=<username>;password=<password>;Initial Catalog=northwind;Data Source=<Your SQL Server name>;");
    Conn->Open();
    注意 记住,若要更改连接字符串参数,以反映正确的值为 SQL Server 服务器。
  14. 设置 try 块来捕获的数据库处理期间可能会发生任何异常。您必须捕捉这些异常中止事务。在 try 块包括两个数据库操作。每个操作更新指定的产品表记录中的其他字段。
    try { 
    
  15. 执行第一个更新到产品表。请将 订购 字段更新产品 id,前两个输入参数中指定为 onOrder 的值。使用下面的 SQL 命令来运行此 SQL 更新:
    SqlCommand * sqlCommand = new SqlCommand("UPDATE Products SET UnitsonOrder = @onOrderString WHERE productID = @pID1String ", Conn);
    sqlCommand->Parameters->Add(new SqlParameter("@onOrderString",SqlDbType::VarChar ,
    	40,ParameterDirection::Input,true,0,0,"Description",DataRowVersion::Current,onOrder.ToString()));
    sqlCommand->Parameters->Add(new SqlParameter("@pID1String", SqlDbType::VarChar,
    	40,ParameterDirection::Input,true,0,0,"Description",DataRowVersion::Current,pID1.ToString()));
    sqlCommand->ExecuteNonQuery();
    
  16. 执行另一个更新到产品表。更新与在 库存量 字段在 inStock 产品 id,第三个和第四个输入参数中指定的值。使用下面的 SQL 命令来运行此 SQL 更新:
    sqlCommand->Parameters->Add(new SqlParameter("@inStockString",SqlDbType::VarChar ,
    	40,ParameterDirection::Input,true,0,0,"Description",DataRowVersion::Current,inStock.ToString()));
    sqlCommand->Parameters->Add(new SqlParameter("@pID2String", SqlDbType::VarChar,
    	40,ParameterDirection::Input,true,0,0,"Description",DataRowVersion::Current,pID2.ToString()));
    sqlCommand->ExecuteNonQuery();
    
  17. 因为这些更新是 COM + 事务的一部分,所以它们作为一个单元提交。将 setCompletecontextUtil 类从 System.EnterpriseServices 命名空间的使用方法提交事务 (在这种情况下两个更新) 如果不引发任何错误:
    ContextUtil::SetComplete(); 
    
  18. 若要关闭罗斯文数据库连接使用下列代码:
    Conn->Close(); }
    
  19. 您必须捕获任何发生时运行 SQL 命令,以便您可以中止整个事务处理的异常:
    catch(Exception * e){ 
    
  20. contextUtilSystem.EnterpriseServices 命名空间中的该 setAbort 方法用于中止整个事务。如果第一个更新是成功,并且第二个更新将失败,都不能更新过帐到产品表中。捕获到的异常将抛给调用方,表明事务已失败:
    ContextUtil::SetAbort();
    throw e; }
    
  21. 为此组件才能正常工作,组件必须具有强名称。生成一个强名称,然后对具有强名称程序集进行签名。若要这样做,请按照下列步骤操作:
    1. 在 Visual Studio.net 命令在键入 sn.exe-k snEnterprise.snk 创建密钥文件。具有强名称签名的程序集有关的详细信息,请参阅.net 框架 SDK 文档。
    2. 将 snEnterprise.snk 复制到您的项目文件夹中。
    3. 在 AssemblyInfo.vc,添加下面的代码行之前或之后其他程序集属性语句:
      [assembly:AssemblyKeyFileAttribute("..\\snEnterprise.snk")]; 
    4. 保存,然后生成您的项目。

完整代码列表

注意 Remember to change your connection string parameters to reflect the correct values for your SQL Server server.
#pragma once

using namespace System;
using namespace System::Data;
using namespace System::Data::SqlTypes;
using namespace System::Data::Common;
using namespace System::EnterpriseServices;
using namespace System::Data::SqlClient;

namespace prjEnterprise
{
	
	[Transaction(TransactionOption::Required,Timeout=5)]
	public __gc class clsES:public ServicedComponent
	{
	public:	SqlConnection * Conn;

	public:	void dbAccess(int pID1, int onOrder, int pID2, int inStock)
		{
			try
			{			
				SqlConnection * Conn = new SqlConnection("user id=<username>;password=<password>;Initial Catalog=northwind;Data Source=<Your SQL Server name>;");
				Conn->Open();
				
				SqlCommand * sqlCommand = new SqlCommand("UPDATE Products SET UnitsonOrder = @onOrderString WHERE productID = @pID1String ", Conn);
				sqlCommand->Parameters->Add(new SqlParameter("@onOrderString",SqlDbType::VarChar ,
					40,ParameterDirection::Input,true,0,0,"Description",DataRowVersion::Current,onOrder.ToString()));
				sqlCommand->Parameters->Add(new SqlParameter("@pID1String", SqlDbType::VarChar,
					40,ParameterDirection::Input,true,0,0,"Description",DataRowVersion::Current,pID1.ToString()));
				sqlCommand->ExecuteNonQuery();
				
				sqlCommand->CommandText = "UPDATE Products SET UnitsinStock = @inStockString WHERE productID = @pID2String" ;
				sqlCommand->Parameters->Add(new SqlParameter("@inStockString",SqlDbType::VarChar ,
					40,ParameterDirection::Input,true,0,0,"Description",DataRowVersion::Current,inStock.ToString()));
				sqlCommand->Parameters->Add(new SqlParameter("@pID2String", SqlDbType::VarChar,
					40,ParameterDirection::Input,true,0,0,"Description",DataRowVersion::Current,pID2.ToString()));
				sqlCommand->ExecuteNonQuery();

				ContextUtil::SetComplete();
				Conn->Close();
			}
			catch(Exception * e)
			{
				ContextUtil::SetAbort();
			
				throw e;
			}			
		}
	};


}
注意 您必须添加公共语言运行库支持的编译器选项 (/ clr:oldSyntax) 成功编译上面的代码示例中的 Visual c + + 2005年中。 在 Visual c + + 2005年中添加公共语言运行库支持编译器选项,请按照下列步骤操作:
  1. 单击 项目,然后单击 $ <ProjectName> 属性

    注意<ProjectName> 是项目的名称的占位符。
  2. 展开 配置属性,然后单击 常规
  3. 单击以选中 公共语言运行库支持、 $ 旧语法 (/ clr:oldSyntax) 在右窗格中 公共语言运行库支持 项目设置中,单击 应用,然后单击 确定
有关公共语言运行库支持编译器选项,请访问下面的 Microsoft 网站:
/ clr (公共语言运行库编译)
http://msdn2.microsoft.com/en-us/library/k8d11d4s.aspx

确认它可以工作

若要测试此代码,创建使用 clsES 类的控制台应用程序项目。在一个的情况下一个事务成功,并更新指定的产品的 订购库存量 域。在第二种情况下为指定的产品的 订购 字段更新成功,但 库存量 字段,对某一产品的更新将失败,因为产品表中不存在指定的产品编号。这将导致一个交易记录失败,交易记录将被忽略。
  1. 启动 Visual Studio.net 或 Visual Studio 2005。
  2. 文件 菜单上指向 新建,然后单击 项目
  3. 项目类型 框中,单击 Visual c + + 项目,然后单击 模板 下的 控制台应用程序 (.NET)

    注意在可视有关 Studio 的 2005 年在 项目类型 框中,单击 Visual c + +,然后单击在 模板 下的 CLR 控制台应用程序
  4. 名称 文本框中键入 testES。请确保选中了 添加到解决方案 选项。
  5. 单击 确定 以将此项目添加到解决方案。
  6. 若要测试 prjEnterprisetestES,您必须添加的引用。在解决方案资源管理器中,右键单击 testES (您刚才添加的) 下的 引用,然后单击 添加引用
  7. 添加引用 对话框。在 项目 选项卡上双击 $ prjEnterprise
  8. 一个引用随即会显示在下 选定组件。单击 确定 以添加对项目的引用。
  9. 将对该项目的引用添加到 System.EnterpriseServices 命名空间。在解决方案资源管理器中,右击 引用,然后单击 添加引用
  10. 添加引用 对话框。 在 .net 选项卡上的 组件名称,双击 $ System.EnterpriseServices
  11. 请确保 System.EnterpriseServices 显示在 选择组件 下。单击 确定
  12. 用鼠标右键单击 testES,然后单击 设为启动项目
  13. 将以下代码粘贴到源 _tmain()testES 类的函数中:
    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");
    	//Console::WriteLine("Error Message: {0}",e->Message);	 
    	//uncomment this line if you must get detailed error information
    }
    
  14. 按 f5 键以运行测试的代码。

    在第 7 步中的代码,dbAccess 在第一次调用成功。产品 1 和产品 2 是产品表中。产品 1 的 onOrder 域会更新以 777,并在 inStock 字段 为 888 更新产品 2。因为此事务成功,您可以在输出窗口中收到以下消息:
    交易记录的一个-成功
    第二次调用 dbAccess 失败。因此,dbAccess 到产品表中的都不能更新语句将过帐到该数据库。虽然产品 1 可能有与其 订购 字段更新为 5,产品 2 不能有其 库存量 字段设置为 -20。由于为约束在产品表定义中定义的 库存量 不允许有负号。因此,将失败 dbAccess 此调用,整个事务处理失败。前 dbAccess 调用时,将保持产品表。catch 语句处理从 dbAccess,事务失败的通知,并在输出窗口中收到以下错误消息:
    事务失败
  15. 通过使用 SQL Server 企业管理器检查罗斯文产品表中的内容。当您查看产品 1 时,订购 域等于 777。当您查看产品 2 时,库存量 字段是 888。因此,dbAccess (这将导致这些字段的不同值) 第二次调用将失败。

故障排除

  • 请确保使用 COM + 服务的任何项目具有强名称。
  • 使用 COM + 服务的任何类必须从服务组件继承。服务的组件位于 System.EnterpriseServices 命名空间中。
  • 同时调试之前提交或中止, 事务可能时间。若要不必超时使用事务属性上的超时属性。在下面的示例中关联的方法都有 1,200 秒超时前完成任何事务:
    [Transaction(TransactionOption::Required,Timeout=1200)]
    
  • 当运行代码时,您可能会收到一些意外的例外情况。若要接收有关这些异常的详细信息,取消注释在第 13 步最后两行:
    Console::WriteLine("Error Message: {0}",e->Message);
    uncomment this line if you must get detailed error information

参考

有关更多的信息,请访问下面的 Microsoft 开发人员网络 (MSDN) 的网站:
COM + 集成: 如何.net 企业服务可以帮助您生成分布式应用程序
服务的组件

属性

文章编号: 815814 - 最后修改: 2007年11月14日 - 修订: 3.2
这篇文章中的信息适用于:
  • Microsoft Visual C++ 2005 Express Edition
  • Microsoft Visual C++ .NET 2003 Standard Edition
关键字:?
kbmt kbsqlclient kbcomplusqc kbcode kbhowtomaster kbhowto KB815814 KbMtzh
机器翻译
注意:这篇文章是由无人工介入的微软自动的机器翻译软件翻译完成。微软很高兴能同时提供给您由人工翻译的和由机器翻译的文章, 以使您能使用您的语言访问所有的知识库文章。然而由机器翻译的文章并不总是完美的。它可能存在词汇,语法或文法的问题,就像是一个外国人在说中文时总是可能犯这样的错误。虽然我们经常升级机器翻译软件以提高翻译质量,但是我们不保证机器翻译的正确度,也不对由于内容的误译或者客户对它的错误使用所引起的任何直接的, 或间接的可能的问题负责。
点击这里察看该文章的英文版: 815814
Microsoft和/或其各供应商对于为任何目的而在本服务器上发布的文件及有关图形所含信息的适用性,不作任何声明。 所有该等文件及有关图形均"依样"提供,而不带任何性质的保证。Microsoft和/或其各供应商特此声明,对所有与该等信息有关的保证和条件不负任何责任,该等保证和条件包括关于适销性、符合特定用途、所有权和非侵权的所有默示保证和条件。在任何情况下,在由于使用或运行本服务器上的信息所引起的或与该等使用或运行有关的诉讼中,Microsoft和/或其各供应商就因丧失使用、数据或利润所导致的任何特别的、间接的、衍生性的损害或任何因使用而丧失所导致的之损害、数据或利润不负任何责任。

提供反馈

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com