By Manish Panchal
Hey!!! Are you surprised with the title of this article?? Lets remove the curtain of techno wonders from your eyes. Actually it is Using COM+ under .NET.
COM+ services have wealth of enterprise functionality that would be very difficult and time consuming to duplicate. Although COM+ services were originally designed for use with COM+ components, it would nice if .NET components could also use them. The problem is that compiled .NET components (that is, assemblies) and compiled COM components adhere to different structural standards; COM components conforms to COM’s binary model and .NET components conforms to the structures outlined in the CLS (Common Language Specification). In order to make .NET components make use of services originally designed for components that fit a different model there are two basic challenges that need to be met.
1. .NET components need to be able to access the objects in the COM+ services object model so that they can refer to them in code.
2. .NET components need to be compiled, packaged and registered in such a way as to be recognizable by COM+ services.
To meet the first goal , Microsoft provides the attributes and classes in the Microsoft.ComServices namespace
To meet the second goal, they provide the RegSvcs.exe registration program.
Developers can use these tools together to COM+ enable .NET components.
The Microsoft.ComServices namespace
In MTS or COM+ programming we need the ObjectContext object in order to perform and join multiple transactional activities automatically. Fortunately this COM+ Service object along with many others, is exposed to .NET components via the Microsoft.ComServices namespace. ContextUtil is the name of the .NET object that wrappers COM's ObjectContext. ContextUtil exposes .NET versions of all the functions that you remember from the ObjectContext object in COM. Here are few ContextUtil methods.
SetAbort: void(); SetComplete: void(); get_ObjectContext: class System.Object(); etc.
Here is the sample code template as an example.
public void OrdPlace(object oCreditCardInfo, object oOrderInfo)
{
try
{
// Debit the credit card
// code goes here...
// Record order shipment
// code goes here...
// Commit the transaction
ContextUtil.SetComplete();
return;
}
catch(Exception e)
{
ContextUtil.SetAbort();
return;
}
}
We have used the ContextUtil object from the Microsoft.ComServices namespace to make our function into transaction. But how do we tell Visual Studio what transaction setting we require ? Thats what we will look at next.
To set the Transaction mode .NET provides namespace level attribute [Transaction]. By prefacing a class with the Transaction attribute, you can tell COM+ Services what sort of transaction level your .NET components require.
namespace ComPlusTran
{
using System;
using System.Runtime.CompilerServices;
using Microsoft.ComServices;
[Transaction(TransactionOption.Required)]
public class Ord : ServicedComponent
{
public void OrdPlace(Object oCreditCardInfo, Object oOrderInfo)
{
// code goes here...
}
}
}
The Transaction attribute lets COM+ Services know the proper transaction level for our component so that we don't have to set it ourselves. As an added bonus, it implicitly invokes SetComplete if the function exits normally.
TransactionOption is an enumeration, with values of Required, None, Ignored, Supported and RequiresNew. These values represent possibel settings in the COM+ administration program.
Registering .NET Components with COM+ Services
Once we have coded our .NET component and compiled it to an assembly DLL, we still have to get it into COM+ Services. You can try adding the assembly DLL to a COM+ application in the same way that you would add a COM DLL. And here is the problem, the assembly doesn't have a TypeLibrary recognizable by COM embedded inside it.
Fortunately, Microsoft provides the RegSvcs.exe as part of the .NET SDK. This command line program expedites the process of adding .NET assemblies to COM+ application. In fact, it does several things, in the following order.
1. It loads and registers the assembly.
2. It creates a Type Library for the assembly.
3. It imports the Type Library into a COM+ Services application.
4. It uses metadata inside the DLL to properly configure the .NET component inside its COM+ Services application.
Here is the syntax for command line.
RegSvcs.exe dotnetassembly.dll [COM+ AppName] [TypeLibrary.tlb]
Once this command is run against any COM transactional .NET assembly, it creates COM+ Application and TypeLibrary with .tlb extension.
Object Pooling
Using COM+'s Object Pooling Services in a .NET component requries that the components class be modified with the [CandBePooled] attribute. As the following snippet of code reveals, various arguments allow you to set the minimum pool size, maximum pool size, and creation timeout period.
[ObjectPooling(MinPoolSize=1, MaxPoolSize=100, CreationTimeOut=30)]
public class Ord : ServicedComponent
Additionaly, the CanBePooled() method from the ServicedComponent interface must return True.