<%@ Page %>

Creating COM+ Aware Components in .NET

Why host .NET components in COM+

COM+ provides many �middle ware� services like increased scalability, Transactions, object pooling, Just-In-Time activation to your components. Enterprise components typically developed in VC++ or VB are often hosted in COM+ to gain above advantages. As you might be aware that .NET components are different than traditional COM components in terms of reference counting, memory management and registration. However, .NET provides a way to host your .NET components inside COM+ environment. In fact it provides easy programmatic configuration options that were lacking in traditional VB or VC++. In this article we will see with an example how to use .NET components with COM+. This article assumes that you are using Visual Studio.NET for your development work. I assume that you are already familiar with MTS/COM+ fundamentals.

Namespaces involved

All the functionality you need to write a COM+ aware component in .NET can be found in System.EnterpriseServices namespace. To indicate to the .NET runtime that your class is COM+ aware, your class must inherit from ServicedComponent class.

Creating your class

Create a new project using VS.NET. For this example I will be using VB.NET but you can choose language of your choice. Add a class to the project with name Employee (Be sure to take care of line breaks). Following is the complete code for the class. We will dissect the code soon.

Imports System.EnterpriseServices
Imports System
Imports System.Data
Imports System.Data.OleDb
Imports System.IO

<Assembly: ApplicationName("EmployeeApp")>
<Assembly: ApplicationActivation(ActivationOption.Library)>

Public Class Employee
    Inherits ServicedComponent

    Public Sub AddEmployee
    (ByVal lname As String, ByVal fname As String)
            Dim cnn As OleDbConnection
            Dim cmd As OleDbCommand
            cnn = New OleDbConnection("Provider=SQLOLEDB.1;
            User ID=sa;Initial Catalog=Northwind;
            Data Source=WIN2000\netsdk")
            cmd = New OleDbCommand
            ("insert into employees(lastname,firstname)
            values('" & lname & "','" & fname & "')", cnn)
            LogMsg("Employee added...")
        Catch ex As Exception
            LogMsg("Employee addition failed...")
        End Try
    End Sub

    <AutoComplete()> Public Sub CalculateBonus()

    End Sub

    Public Overrides Sub Activate()
        LogMsg("Object Activated...")
    End Sub

    Public Overrides Sub Deactivate()
        LogMsg("Object Deactivated...")
    End Sub

    Public Overrides Function CanBePooled() As Boolean
        LogMsg("Can be pooled called...")
        Return True
    End Function

    Private Sub LogMsg(ByVal msg As String)
        Dim writer As StreamWriter
        writer = System.IO.File.AppendText("mylog.txt")
    End Sub
End Class

Let us dissect the code :

  • We have imported System.EnterpriseServices namespace
  • Marking class with assembly level attributes : We have created a class called Employee. We can mark this class with certain assembly level attributes that allow for dynamic registration of the assembly. The lines
    <Assembly: ApplicationName("EmployeeApp")>
    <Assembly: ApplicationActivation(ActivationOption.Library)>
    do just that. The ApplicationName attribute tells the COM+ application name as appeared in COM+ explorer and ApplicationActivation specifies whether the component will act as library or server application.
  • As discussed earlier the class Employee is derived from ServicedComponent. It is then marked with Transaction attribute. The values for this attribute are same as in traditional VB/VC++ development i.e. Required, RequiresNew, Supported etc.
  • The class is additionally marked with ObjectPooling attribute that specifies values for minimum and maximum object instances
  • The employee class has a method called AddEmployee that inserts a new employee in Employee table of Northwind database. Since the class is marked to require a transaction each method will execute in a transaction (existing or new). Once the INSERT has been executed we need to either commit or rollback the transaction. This is done via static methods of ContextUtil class. The method SetComplete is used to commit a transaction where as SetAbort is used to rollback a transaction.
  • Next, I have also inserted an empty method called CalculateBonus. This method is marked with an attribute AutoComplete which means that once the method execution is over the transaction is automatically committed (equivalent to ContextUtil.SetComplete). In case of any error the transaction will be rolled back (equivalent to ContextUtil.SetAbort).
  • We have also enabled object pooling for the component. Just for sake for testing I have overriden Activate, Deactivate and CanBePooled methods.

Compiling the component

Before you compile your class you need to sign your assembly with a strong name. In VS.NET IDE you can go to project properties dialog and do that. Signing an assembly with a key file ensures its uniqueness on a given machine.

Creating client for your component

For the purpose of testing you can create any kind of client application like Console application, WinForm application or even ASP.NET application. Then as with any other component you can create instances of the Employee class. Note here that unlike traditional MTS/COM+ development we have not 'manually' registered our component inside the component explorer. Run the client application and then check the log file "mylog.txt" examine sequence of method calls.

Bipin Joshi is an independent software consultant and trainer by profession specializing in Microsoft web development technologies. Having embraced the Yoga way of life he is also a yoga mentor, meditation teacher, and spiritual guide to his students. He is a prolific author and writes regularly about software development and yoga on his websites. He is programming, meditating, writing, and teaching for over 27 years. To know more about his private online courses on ASP.NET and meditation go here and here.

Posted On : 05 November 2001

Tags : .NET Framework Architecture VB.NET C# Components