asp tutorials, asp.net tutorials, sample code, and Microsoft news from 15Seconds
Data Access  |   Troubleshooting  |   Security  |   Performance  |   ADSI  |   Upload  |   Email  |   Control Building  |   Component Building  |   Forms  |   XML  |   Web Services  |   ASP.NET  |   .NET Features  |   .NET 2.0  |   App Development  |   App Architecture  |   IIS  |   Wireless
 
Pioneering Active Server
 Power Search





Active News
15 Seconds Weekly Newsletter
• Complete Coverage
• Site Updates
• Upcoming Features

More Free Newsletters
Reference
News
Articles
Archive
Writers
Code Samples
Components
Tools
FAQ
Feedback
Books
Links
DL Archives
Community
Messageboard
List Servers
Mailing List
WebHosts
Consultants
Tech Jobs
15 Seconds
Home
Site Map
Press
Legal
Privacy Policy
internet.commerce














internet.com
IT
Developer
Internet News
Small Business
Personal Technology
International

Search internet.com
Advertise
Corporate Info
Newsletters
Tech Jobs
E-mail Offers

HardwareCentral
Compare products, prices, and stores at Hardware Central!

Utilizing COM+ Services without Serviced Components
By Thiru Thangarathinam
Rating: 4.5 out of 5
Rate this article


  • email this article to a colleague
  • suggest an article

    Introduction

    COM+ Services, referred to as Enterprise Services, provide .NET developers with a powerful set of services for developing robust and scalable server applications. Enterprise Services in Windows Server 2000 shipped with COM+ version 1.0 and provided services such as transactions, role-based security, queued components, and loosely coupled events. With the release of Windows XP and Windows Server 2003, COM+ version 1.5 was released. Even though Windows XP came bundled with COM+ 1.5, some of the features were available only in Windows Server 2003. For example, one of the new features of COM+ 1.5 is the ability to leverage COM+ services without deriving your class from the ServicedComponent class. This functionality is supported only in Windows Server 2003. In this article, we will focus on this new feature and understand how to leverage the COM+ features without deriving the class from the ServicedComponent class.

    download source code

    In the .NET Framework, there is a separate namespace called System.EnterpriseServices that contains all the classes required for providing COM+ services to applications. For an introduction to COM+, please take a look at the following link from TechNet: Introduction to COM and COM+.

    Problems with the Serviced Component Approach

    Previously, if you wanted to use COM+ services from a .NET application, you had to go through the following steps.

    • Derive your class from the ServicedComponent class
    • Create a strong key and associate that with the assembly
    • Register the component with the component services explorer either manually or using the automatic registration feature.

    As you can see, use of COM+ services from a .NET application involves a number of steps that you need to go through before you can leverage COM+ services. Wouldn't it be nice if we could enter into a context by using a couple of lines of code and leveraging COM+ services from within that context? This is exactly what you can accomplish using Windows Server 2003 and .NET Framework 1.1. This new feature will be the focus of this article.

    Before we take a look at the new feature, let us take a moment to understand the new classes in COM+ 1.5 that make this feature a reality. Two new classes that we will be concentrating on in this article are ServiceConfig and ServiceDomain.

    ServiceConfig

    This class allows you to specify the services such as transaction monitoring, role based security, and so on that should be available from the context that is created dynamically for the object. This class exposes a number of important methods that enable you to configure those services. Some of the important properties exposed by the ServiceConfig class include:

    • TrackingEnabled: This boolean property allows you to specify if the tracking information is enabled. Basically, the tracker is a reporting mechanism used by the monitoring applications to watch running COM+ components. You may have already seen this in action if you have seen the spinning component icons in the component services explorer.
    • TrackingAppName: Using this property, you can specify a text string that will be used to represent the COM+ application in component services explorer.
    • TrackingComponentName: This property allows you to specify a text string that will be used to represent the component in component services explorer.
    • TransactionTimeout: This property enables you to specify the transaction time-out for a new transaction.
    • Transaction: This is a very important property. With it you can specify how transactions are used in the enclosed code. To this property you can assign any of the values provided by the TransactionOption enum constant.
      • Disabled: This option is used to ignore any transaction in the current context.
      • NotSupported: This option is used to create the component in a context without any enclosing transaction.
      • Required: When specified, this option is used to share a transaction, if one exists. If there is no transaction, then a new transaction is created and the code runs within the scope of that new transaction.
      • RequiresNew: This option allows you to create a new transaction irrespective of the state of the current context.
      • Supported: When specified, this option is used to share a transaction, if one exists. If there is no transaction, then the code runs without any transaction.

    ServiceDomain

    The ServiceDomain class makes it possible for a .NET managed object to run in its own context. You can indicate that the object should run in its own context by using the Enter and Leave methods of the ServiceDomain class. Whenever you want the object to run in its own context, you need to use the combination of the Enter and Leave methods. The code that is enclosed within this block can use COM+ services. It is also possible for you to nest the Enter and Leave methods. However, you need to ensure that for every Enter method call there is a corresponding Leave method. Now that we have reviewed these classes, let us take a look at an example to illustrate the concepts.

    Implementation of a Simple Component

    In this section, we will create a simple component to demonstrate how to use COM+ services without having to derive from the ServicedComponent class. We will start by creating a new Visual C# class library project named SimpleComponent. Once the project is created, we will rename the default class from Class1 to UtilClass. Then we modify the code in the UtilClass.cs file to look like the following.

    using System;

    using System.EnterpriseServices;

     

    namespace SimpleComponent

    {

          

           public class UtilClass

           {

                  public UtilClass()

                  {                   

                  }

     

                  public bool IsMethodRunningInTransaction()

                  {

                         bool isInTransaction;

                         ServiceConfig config = new ServiceConfig();

                         config.TrackingEnabled = true;

                         config.TrackingAppName = "SimpleComponent Application";

                         config.TrackingComponentName = "SimpleComponent";

                         config.Transaction = TransactionOption.Required;                    

                         ServiceDomain.Enter(config);

                         //Check if the method is running in a transaction     

                         isInTransaction = ContextUtil.IsInTransaction;

                         ServiceDomain.Leave();

                         return isInTransaction;

                  }

           }

    }

    As you can see from the above code, the UtilClass is very simple, and it contains only one method named IsMethodRunningInTransaction. As the name suggests, this method is used to determine whether the code inside the method is running in a transaction. Let us examine the method's code.

    To start with, we create an instance of the ServiceConfig object. Then we set important properties such as TrackingEnabled, TrackingAppName, and TrackingComponentName and Transaction on the ServiceConfig object. Note that we set the Transaction property of the ServiceConfig object to TransactionOption.Required. This ensures that the code enclosed by the ServiceDomain.Enter and ServiceDomain.Leave methods always runs within the scope of a transaction.

    
    	ServiceConfig config = new ServiceConfig();
    	config.TrackingEnabled = true;
    	config.TrackingAppName = "SimpleComponent Application";
    	config.TrackingComponentName = "SimpleComponent";
    	config.Transaction = TransactionOption.Required;	
    
    
    Here we invoke the Enter method of the ServiceDomain object, passing in the previously created ServiceConfig object. Because of this, the context specified by the ServiceConfig object will be pushed onto the context stack and made the current context.
    	
    	ServiceDomain.Enter(config);
    
    
    From within this newly created context, we invoke the IsInTransaction method of the ContextUtil class to determine if the code is running in a transaction. As you would expect, this will return true due to the value assigned to the Transaction property.
    
    	//Check if the method is running in a transaction	
    	isInTransaction = ContextUtil.IsInTransaction;
    
    
    Here we exit the current context by invoking the Leave method of the ServiceDomain object. Because of this, the current context is popped from the context stack, and the context that was running when Enter was invoked becomes the original context.
    
    	ServiceDomain.Leave();
    
    
    Finally, we return the value contained in the variable isInTransaction to the caller of the method.
    
    	return isInTransaction;
    
    

    Implementation of SimpleComponentClientApp

    Now that we have created the component, let us test it by creating a client application. For this example, we will consider a new Visual C# Windows Application named SimpleComponentClientApp. We will add this project to the existing solution by selecting File->Add Project->New Project from the menu. Once the project is created, we will reference the SimpleComponent using the Project-> Add Reference option from the menu. Then we import the SimpleComponent namespace by means of a using keyword.

    
    using SimpleComponent;
    
    
    Then we will add a command button named btnInvoke and add the following lines of code under the click event.
    
    private void btnInvoke_Click(object sender, System.EventArgs e)
    {
    	UtilClass util = new UtilClass();
           MessageBox.Show(util.IsMethodRunningInTransaction().ToString());
    }
    
    
    As you can see from the above, the code is straightforward. First, we create an instance of the UtilClass and then simply invoke the IsMethodRunningInTransaction method of the UtilClass. If you bring up the component services explorer while the client application is running and open up the running processes node in the treeview, you will find that the SimpleComponent is running under the SimpleComponent Application. Remember that at the time of creating the ServiceConfig object, we set the TrackingAppName and TrackingComponentName to SimpleComponent Application and SimpleComponent respectively.

    Our component appears under the Running Processes node, since we are trying to use the COM+ services dynamically at run time. When the client application is shut down, the SimpleComponent will disappear from the Running Processes node.

    Debugging the Component

    So far, we have seen how to configure a component that is capable of creating a context dynamically and make it possible for the component to take advantage of COM+ services. You might wonder how difficult it is to debug such a component. Debugging a component of this nature is very simple and straightforward. All you need to do is to set breakpoints in the component code and run your client application.

    For example, let us consider the client application that we created previously. As you might remember, the client project and the component project are part of the same solution. To debug the SimpleComponent, open up the UtilClass and set break points in the code. Now if you run the client application, you will automatically hit the breakpoint. Once the breakpoint is hit, you can debug this component exactly the same way you debug any other component.

    The above screenshot shows the breakpoint in the SimpleComponent code with the debugger in action. Now that you have understood the basics of using COM+ services without using serviced components, let us consider an advanced example wherein we will use the ServiceConfig object to implement distributed transactions.

    Implementation of a Transactional Component

    For the purposes of this example, we will create a new Visual C# Class Library project named TransactionDemoComponent. In this project, we will add three classes named Dept, Employee, and TransactionalClass. To the Dept and Employee classes, we will add methods to add a new employee and a dept respectively. From the TransactionalClass, we will invoke the methods in these classes to add a new dept and an employee. Since we want both of these operations to be running as part of a transaction, we will use the ServiceConfig object in the TransactionalClass to use the distributed transactions capability of COM+ services.

    After creating the project, we will rename the default class to Dept and add the following lines of code to the Dept class.

    public class Dept

    {

           public Dept()

           {

           }

     

           public int AddDept(string deptName, string deptDescription)

           {

                  int deptNo;

                  string connString =

                  "server=localhost;uid=sa;pwd=thiru;database=15Seconds;";

                  string commandName = "AddDept";

                  using (SqlConnection conn = new SqlConnection(connString))

                  {

                         conn.Open();                     

                         SqlCommand command = new SqlCommand(commandName,conn);

                         //Set the Command Type to Stored Procedure

                         command.CommandType = CommandType.StoredProcedure;

                         //Create the DeptName parameter and set its properties

                         SqlParameter paramDeptName = new

                               SqlParameter("@DeptName", SqlDbType.VarChar,50);

                         paramDeptName.Direction = ParameterDirection.Input;

                         paramDeptName.Value = deptName;

                         command.Parameters.Add(paramDeptName);

                         //Create the DeptDescription parameter and set its value

                         SqlParameter paramDeptDesc = new

                         SqlParameter("@DeptDescription",SqlDbType.VarChar,250);

                         paramDeptDesc.Direction = ParameterDirection.Input;

                         paramDeptDesc.Value = deptDescription;

                         command.Parameters.Add(paramDeptDesc);

    //Create the Return parameter and set its properties

                         SqlParameter paramReturnValue = new

                         SqlParameter("@@identity",SqlDbType.VarChar,250);

                         paramReturnValue.Direction =

                         ParameterDirection.ReturnValue;                       

    command.Parameters.Add(paramReturnValue);      

                         //Execute the Stored Procedure

                         command.ExecuteNonQuery();

                         //Get the identity value from the stored procedure

                         deptNo = (int)command.Parameters["@@identity"].Value; 

                  }

                  return deptNo;                                        

           }

    }

    As you can see from the above code, the Dept class contains only one method named AddDept, which executes a stored procedure named AddDept to add a dept to the database. After inserting the dept details into the database, the stored procedure returns the identity value of the newly inserted dept ID to the caller. We capture that returned ID by using the Parameters collection of the SqlCommand object, and we do this after executing the stored procedure by means of an ExecuteNonQuery method call. The Stored procedure AddDept is defined as follows.

    
    CREATE proc AddDept
    @DeptName varchar(50) ,
    @DeptDescription varchar(250) 
    as
    
    set nocount on
    insert into Dept(DeptName, DeptDescription) Values(@DeptName, @DeptDescription)
    return @@identity
    GO
    
    
    Now that we have created the Dept class, let us take a look at the code of the Employee class.

    public class Employee

    {

    public Employee()

           {

           }

     

           public int AddEmployee(string empName, int deptNo)

           {

                  string connString =

                  "server=localhost;uid=sa;pwd=thiru;database=15Seconds;";

                  string commandName = "AddEmployee";

                  int empNo;

                  using (SqlConnection conn = new SqlConnection(connString))

                  {

                         conn.Open();                     

                         SqlCommand command = new SqlCommand(commandName,conn);

                         //Set the Command Type to Stored Procedure

                         command.CommandType = CommandType.StoredProcedure;

                         //Create the EmpName Parameter

                         SqlParameter paramEmpName = new

    SqlParameter("@EmpName", SqlDbType.VarChar,50);

                  paramEmpName.Direction = ParameterDirection.Input;

                         paramEmpName.Value = empName;

                         command.Parameters.Add(paramEmpName);

                         //Create the DeptNo Parameter

                         SqlParameter paramDeptNo = new

                               SqlParameter("@DeptNo",SqlDbType.Int);

                         paramDeptNo.Direction = ParameterDirection.Input;

                         paramDeptNo.Value = deptNo;

    command.Parameters.Add(paramDeptNo);                                       //Create the Return parameter and set its properties

                         SqlParameter paramReturnValue = new

                               SqlParameter("@@identity",SqlDbType.VarChar,250);

                         paramReturnValue.Direction =

                               ParameterDirection.ReturnValue;

                                          command.Parameters.Add(paramReturnValue);      

                         //Execute the Stored Procedure

                         command.ExecuteNonQuery();

                         //Get the identity value from the stored procedure

                         empNo = (int)command.Parameters["@@identity"].Value;  

                  }

                  return empNo;             

           }

    }

    As you can see from the above code, the Employee class is very similar to the Dept class in that it also contains only one method, named AddEmployee, that simply adds the details of an employee to the database. Similar to the AddDept method, the AddEmployee method also returns the ID of the newly added employee to the caller.

    Implementation of the TransactionalClass

    Now that we have developed the Employee and Dept classes, let us turn our focus to the TransactionalClass, which is responsible for ensuring that the details of a dept and an employee are added as part of a single transaction.

    public class TransactionalClass

    {

           public TransactionalClass()

           {

           }

     

           public bool AddEmployeeDept(string deptName, string deptDescription,

                                      string empName)

           {

                  ServiceConfig config = new ServiceConfig();

                  //Set the properties of ServiceConfig object

                  config.TrackingEnabled = true;

                  config.TrackingAppName = "SimpleComponent Application";

                  config.TrackingComponentName = "SimpleComponent";

    //Set the TransactionOption to Required to indicate that a new //Transaction Context needs to be created

                  config.Transaction = TransactionOption.Required; //Enter inside the Service Domain to use COM+ Services

                  ServiceDomain.Enter(config);

                  Dept department = new Dept();

                  int deptNo = department.AddDept(deptName, deptDescription);

                  Employee emp = new Employee();

                  emp.AddEmployee(empName, deptNo);

                  ServiceDomain.Leave();

                  return true;

           }

    }

    The AddEmployeeDept method starts by creating an instance of the ServiceConfig class. After that, it assigns values to properties such as TrackingEnabled, TrackingAppName, and TrackingComponentName. As we already mentioned, these properties are used to determine if and how the tracking information about the component is reported. Then we set the Transaction property to TransactionOption.Required. This ensures that the object always runs within the scope of a transaction. Once we assign appropriate values to the ServiceConfig object, we are ready to enter inside the context. This is accomplished using the ServiceDomain.Enter method. Once we are within the context of a service domain, we can now invoke the AddDept, and AddEmployee methods through their corresponding objects. Since we have already set the Transaction property to TransactionOption.Required, the code that is enclosed within Enter and Leave methods will always run in a transaction. This means that if there is an exception during the execution of any of the methods, the transaction will be rolled back, ensuring the consistency of the data.

    Implementation of the Client Application

    To test the Transactional component, let us create a simple Visual C# Windows application named TransactionDemoComponentClient. Once the project is created, we will reference the TransactionDemoComponent using the Project->Add Reference menu. After that, add a command button named btnInvoke to the form and modify the Click event of the command button to look like the following.

    
    private void btnInvoke_Click(object sender, System.EventArgs e)
    {
    	TransactionalClass trans = new TransactionalClass();
    	MessageBox.Show(trans.AddEmployeeDept("Production Dept", 
    		"Production Dept Descr","Thiru").ToString());
    }
    
    
    If the AddEmployeeDept method executes successfully, you will see a Boolean true value in the message box. If there is an exception during the execution of the AddEmployeeDept method, no information will be added to the database.

    Prerequisites

    To execute the code that is available for download, you need to have the following software installed on your machine:

    • Windows 2003 Server
    • SQL Server 2000 or SQL Server 7.0
    • Visual Studio.NET 2003

    Conclusion

    In this article, we have understood the steps involved in creating components that can use COM+ services without having to derive from the ServicedComponent class. We also demonstrated the use of this excellent feature by leveraging the distributed transaction capability of COM+. With this new powerful capability, creating a component that uses COM+ services is a very simple process, greatly improving developer productivity.

    I hope you find this article useful, and thanks for reading.

    About the Author

    Thiru has many years of experience in architecting, designing, developing and implementing applications using Object Oriented Application development methodologies. He also possesses a thorough understanding of software life cycle (design, development and testing).

    He is an expert with ASP.NET, .NET Framework, Visual C#.NET, Visual Basic.NET, ADO.NET, XML Web Services and .NET Remoting and holds MCAD for .NET, MCSD and MCP certifications.

    Thiru has authored numerous books and articles. He can be reached at thiruthangarathinam@yahoo.com.

  • Rate This Article
    Not HelpfulMost Helpful
    1 2 3 4 5
    Other Articles
    Feb 23, 2005 - My Feature in Visual Basic 2005
    In this article, Thiru Thangarathinam demonstrates the different classes and features available through the My namespace. By providing a speed-dial that allows you to more quickly and effectively utilize .NET framework functionalities in your application, the My feature provides huge productivity improvements for .NET developers.
    [Read This Article]  [Top]
    Oct 6, 2004 - Creating Triggers Using Managed Code in SQL Server 2005
    Thiru Thangarathinam discusses taking advantage of the integation between the .NET CLR and SQL Server 2005 in order to do things like create triggers using managed code.
    [Read This Article]  [Top]
    Sep 8, 2004 - Custom Object Data Binding with .NET
    Developers often use brute force coding to marshal data between the GUI and application objects. In this article, Luther Stanton explains how to use .NET's out-of-the box data-binding functionality to make this job much easier.
    [Read This Article]  [Top]
    Aug 17, 2004 - The Perfect Service - Part 2
    Ambrose Little provides the complete source code for his 'Perfect Service' and explains how the .NET Service Manager enables features such as drag-n-drop deployment.
    [Read This Article]  [Top]
    Aug 12, 2004 - Middle-Tier Hosting: Enterprise Services, IIS, DCOM, Web Services, and Remoting
    There is broad-reaching debate about remoting, Web services, Enterprise Services, and DCOM. In short, it is a debate about the best technology to use when implementing client/server communication in .NET. Rocky Lhotka shares his thoughts on the issue while offering clear explanations of basic application architecture terminology.
    [Read This Article]  [Top]
    Jul 21, 2004 - COM Interop Exposed
    This article provides and excellent foundation for COM Interop. It reviews COM's background, explains how VB6 interacts with COM, and then shows how to design .NET components to smoothly interact with COM.
    [Read This Article]  [Top]
    Jun 24, 2004 - The Perfect Service - Part 1
    The first article in this two-part series shows how to get Ambrose Little's .NET Service Manager running and then how to add plug-n-play services to it using drag-n-drop or XCOPY.
    [Read This Article]  [Top]
    May 25, 2004 - Generics In-Depth
    Although generics are extremely useful, they also seem to have a certain mystique that cannot be readily explained. This article hopes to remove that aura of mystery by showing just how easy it is to use generics and how useful they can be in many common situations.
    [Read This Article]  [Top]
    May 11, 2004 - SharePoint Security and .NET Impersonation
    When implementing custom components that require access to restricted resources, implicit impersonation must be used. Jay Nathan shows how to create a class that makes using .NET Impersonation a snap.
    [Read This Article]  [Top]
    Mar 23, 2004 - Exploiting .NET's Advanced Deployment Features
    Tony Arslan shows how to use VS .NET's custom deployment feature to create configuration files on the target machine during installation.
    [Read This Article]  [Top]
    Mailing List
    Want to receive email when the next article is published? Just Click Here to sign up.

    Support the Active Server Industry



    JupiterOnlineMedia

    internet.comearthweb.comDevx.commediabistro.comGraphics.com

    Search:

    Jupitermedia Corporation has two divisions: Jupiterimages and JupiterOnlineMedia

    Jupitermedia Corporate Info


    Legal Notices, Licensing, Reprints, & Permissions, Privacy Policy.

    Advertise | Newsletters | Tech Jobs | Shopping | E-mail Offers