Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Microsoft Visual C++ .NET Professional Projects - Premier Press

.pdf
Скачиваний:
180
Добавлен:
24.05.2014
Размер:
26 Мб
Скачать
☆

800 Project 8 .NET ASSEMBLIES WITH MANAGED C++ AND .NET

 

 

Y

 

L

 

F

 

M

 

A

 

FIGURE 27-3 The Visual C++ New Project dialog box

E

 

T

 

 

2. Name the project ProcessOrder. Click on the OK button.

3. From the Solution Explorer, open the file ProcessOrder.h. This file will have the declaration for a class named Class1. Following is the code generated by the IDE:

#pragma once

using namespace System; namespace ProcessOrder

{

public __gc class Class1

{

// TODO: Add your methods for this class here.

};

}

From the previous chapter, you know about accessing the data using the SQL Server .NET Provider. Next, you need to import the required DLLs and add the namespace declarations. You also need to include the System.Enterpriseservices.dll to access the COM+ services.

#pragma once

#using <mscorlib.dll>

#using <System.dll>

Team-Fly®

USING COM+ SERVICES FROM .NET ASSEMBLIES

Chapter 27

 

801

 

#using <System.Data.dll>

 

 

 

 

 

 

 

 

#include <tchar.h>

 

 

 

 

#using <System.Enterpriseservices.dll>

 

 

 

 

using namespace System;

 

 

 

 

using System::String;

 

 

 

 

using namespace System::Data;

 

 

 

 

using namespace System::Data::SqlClient;

 

 

 

 

using namespace System::EnterpriseServices;

 

 

 

 

using namespace System::Runtime::InteropServices;

 

 

 

 

Any class that needs to use the COM+ services will have to derive from the ServicedComponent class. Add the following declaration, too:

using System::EnterpriseServices::ServicedComponent;

public __gc class Class1: public ServicedComponent

{

To specify that the class will be using transactions, use the Transaction attribute:

[Transaction(TransactionOption::Required)]

public __gc class Class1: public ServicedComponent

{

// TODO: Add your methods for this class here.

};

The Transaction attribute can have the following values:

TransactionOption::Required. This creates a new transaction if the calling application is not in a transaction.

TransactionIsolationLevel::Serializable. This prevents modification of data until the transaction is complete.

Timeout. This is used to specify the time after which the transaction should abort.

To the class Class1, add a new method updateOrders with the following signature:

public:

int updateOrders(String *strProdID,String *strCustID, String *strSessionID, String

*strOrderDate, String *strOrderStatus)

{

802 Project 8 .NET ASSEMBLIES WITH MANAGED C++ AND .NET

This method first needs to insert a record into the Orders table. You have already seen how this can be easily achieved using the SQL Server .NET Provider:

//Create a Connection object

SqlConnection *sConn=new SqlConnection();

//Initialize and open the connection string sConn->set_ConnectionString(“Data Source=Server1;Initial Catalog=ArtShop;Integrated Security=SSPI”);

//Open the connection sConn->Open();

SqlDataAdapter *dataAdapter=new SqlDataAdapter();

String *strCmd;

try{

//Construct the command string.

strCmd=”insert into Orders(ProdId,CustId,SessionID,OrderDate,OrderStatus) values(“;

strCmd=strCmd->Concat(strCmd,strProdID); strCmd=strCmd->Concat(strCmd,”,”); strCmd=strCmd->Concat(strCmd,strCustID); strCmd=strCmd->Concat(strCmd,”,’”); strCmd=strCmd->Concat(strCmd,strSessionID); strCmd=strCmd->Concat(strCmd,”’,’”); strCmd=strCmd->Concat(strCmd,strOrderDate); strCmd=strCmd->Concat(strCmd,”’,’”); strCmd=strCmd->Concat(strCmd,strOrderStatus); strCmd=strCmd->Concat(strCmd,”’)”);

//Create a DataAdapter object and execute the command dataAdapter->UpdateCommand=new SqlCommand(NULL,sConn); dataAdapter->UpdateCommand->CommandText=strCmd; dataAdapter->UpdateCommand->ExecuteNonQuery();

}

catch(Exception *e)

{

USING COM+ SERVICES FROM .NET ASSEMBLIES Chapter 27 803

//Remove the following comment during debugging //Console::WriteLine(e->Message);

//If there was an error in the record insertion //cancel the entire operation and return an error.

ContextUtil::SetAbort();

return 1;

}

Next, update the Products table and set the ProdStatus of the product whose ID is passed as a parameter to Sold:

//Update the status of the product in product table to ‘sold’

SqlConnection *sConn2=new SqlConnection(); sConn2->set_ConnectionString(“Data Source=saik-d185;Initial Catalog=ArtShop;Integrated Security=SSPI”);

sConn2->Open();

SqlDataAdapter *dataAdapter2=new SqlDataAdapter();

try

{

//Construct the command string

strCmd=”Update Product set ProdStatus=’Sold’ where ProdID=’”; strCmd=strCmd->Concat(strCmd,strProdID); strCmd=strCmd->Concat(strCmd,”’”);

//Create the DataAdapter object and execute the query dataAdapter2->UpdateCommand=new SqlCommand(NULL,sConn2); dataAdapter2->UpdateCommand->CommandText=strCmd; dataAdapter2->UpdateCommand->ExecuteNonQuery();

//If no exceptions were raised till here commit the transaction.

ContextUtil::SetComplete();

}

catch(Exception *e)

{

//Console::WriteLine(e->Message);

//If there was an error rollback the transaction.

804 Project 8 .NET ASSEMBLIES WITH MANAGED C++ AND .NET

ContextUtil::SetAbort(); return 1;

}

//a normal exit return 0;

}

Registering the ProcessOrder Component with COM+ Services

Before the .NET component becomes accessible to the COM+ Services, it has to be registered. The .NET Framework provides a utility, RegSvcs.exe, just for that. This utility can be used to:

1.Register the assembly.

2.Create a type library from the assembly.

3.Create a COM+ services application and properly configure it.

The syntax of the command is as follows:

RegSvcs ProcessOrder.dll [COM+ Application name] [Type Library name]

However, the utility expects the DLL to have a strong name. Try it and you will get an error message, as shown in Figure 27-4.

FIGURE 27-4 Executing the RegSvcs.exe utility to register the assembly

To create a strong name, you will have to create a key file. Again, we will use a command-line utility, sn.exe, to do it:

sn –k key1.snk

USING COM+ SERVICES FROM .NET ASSEMBLIES Chapter 27 805

NOTE

You can find this utility in the Program Files\Microsoft Visual Studio .Net\ FrameWorkSDK\bin folder.

This will create a file, key1.snk, which will contain the public and private keys for the assembly in the binary format. Copy the file to the project folder. From the Solution Explorer, open the file assemblyinfo.cpp and update the key file attribute:

[assembly:AssemblyDelaySignAttribute(false)];

[assembly:AssemblyKeyFileAttribute(“key1.snk”)];

[assembly:AssemblyKeyNameAttribute(“”)];

Build the assembly again. Now register the assembly with the COM+ catalog. The assembly will get registered as shown in Figure 27-5.

FIGURE 27-5 Executing the RegSvcs.exe utility and its output

Now that the assembly has a strong name, you can transfer it to the global assembly cache:

Gacutil /i ProcessOrder.dll

Once in the global assembly cache, the component can be accessed from a client in any folder, just like a COM component.

Testing the Component

To test the component, you will create a VBScript file. Create a VBScript file and add the following code to it:

806 Project 8 .NET ASSEMBLIES WITH MANAGED C++ AND .NET

dim pObj

set pObj=CreateObject(“ProcessOrder.Class1”)

msgbox pObj.updateOrders( “2”,”2”,”222222”,”12/12/1990”,”Pending”)

Open the SQL Server Enterprise Manager and check the contents of the table Orders. The record should be added to it. If you want the transaction to fail, try calling the updateOrders method with an invalid value for ProdID.

Try changing the name of the table in the second part of the transaction (updating the Product table) to any invalid value. This way, the first insert command for the Orders table will succeed. However, the update command will fail. Since both the operations are a part of the same transaction, even the insert into the Orders table will be rolled back.

Summary

In this chapter, you created a .NET assembly that uses COM+ services to handle transactions. You saw that COM+ services plumbing is accessible to .NET applications and provides some useful functionality. MTS introduced component services that developers could use to provide transaction support, object pooling, declarative security, and other features to create enterprise applications. Windows 2000 COM+ services improved component services, introduced new features, and made it a part of the operating system. The EnterpriseServices namespace makes all of this accessible to .NET applications too.

PART X

Professional

Project – 9

This page intentionally left blank

Project 9

XML with

VC++.NET