Enterprise Services: System.EnterpriseServices


Modern multitier applications often locate the bulk of their business logic in the middle tier. Much of the time, writing this logic with a technology such as ASP.NET is perfectly adequate. In some cases, however, especially for applications that need to be very scalable and require features such as distributed transactions, more is required. Prior to .NET, the Microsoft technology that provided these services was known as COM+. With the advent of the .NET Framework, those services are still available to CLR-based applications. In fact, the services themselves haven't changed much at all, but two things about them have: how they're accessed and what they're called. Now known as Enterprise Services, all of the traditional COM+ services for building robust, scalable applications are usable by applications written on the .NET Framework.

The types in System.EnterpriseServices allow access to COM+ services


What Enterprise Services Provides

For a class to use Enterprise Services, that class must inherit from EnterpriseServices.ServicedComponent. Because of this, a class using these services is referred to as a serviced component. Serviced components have access to the full range of what Enterprise Services provides, including the following:

  • Support for (possibly distributed) transactions

  • Just-in-time activation (JITA), which optimizes server resources by allowing objects to exist only when they're needed

  • Object pooling, which allows instances of a class to be pooled and reused rather than being destroyed and recreated

  • Role-based authorization services that allow Enterprise Services to verify a client's role and then grant services only to clients in specific roles

Classes that use Enterprise Services are known as serviced components


One of the innovations brought by COM+ (or more correctly, by Microsoft Transaction Server, the original incarnation of this technology) was the ability to control what services a component received by setting attributes in a configuration file. In the .NET Framework, however, attributes are supported directly. Every assembly can have extra metadata represented as attributes, and attribute values can be set in the source code of a CLR-based application. This built-in support for attributes matches well with how COM+ provides its services, and so an Enterprise Services developer specifies what services should be used by including attributes directly in his code. And because it's sometimes useful to be able to change a component's attributes after the assembly that contains it has been installed, it's still possible to set or modify a deployed component's attributes if desired.

Serviced components use attributes to specify what services an application needs


Here's a simple VB.NET class that shows how attributes can be used to control the use of Enterprise Services transactions:

<Transaction(TransactionOption.Required)> _     Public Class BankAccount         Inherits ServicedComponent     <AutoComplete()> _     Public Sub Deposit(Account As Integer, _                        Amount As Decimal)          ' Add Amount to Account     End Sub     <AutoComplete()> _     Public Sub Withdrawal(Account As Integer, _                           Amount As Decimal)         ' Subtract Amount from Account     End Sub End Class


This class, called BankAccount, inherits from Serviced Component, as is required for any class that wishes to use Enterprise Services. The class definition is also preceded with an attribute indicating that this class uses the Required setting for transactions. This means that whenever a client calls one of the class's methods, Enterprise Services will automatically wrap the work done by that method in the all-or-nothing embrace of a transaction.

Perspective: System.EnterpriseServices vs. System.Transactions

In Enterprise Services and its predecessors, support for transactions is bundled together with other services, such as just-in-time activation and role-based authorization. In fact, ending an Enterprise Services transaction also requires destroying any in-memory objects that were participating in that transaction. The people who designed this technology were smart guys, and so there's a good argument for grouping these behaviors together. That argument goes like this: Objects that use transactions, especially the more complex distributed transactions that Enterprise Services make possible, are typically part of an application's middle-tier business logic. This code needs to scale, and forcing transactional objects to be stateless (that is, to not maintain any in-memory state between transactions) is a great way to do this. Prohibiting objects from retaining state across a transaction boundary also eliminates the possibility of the object's in-memory state not matching the state stored in, say, a database involved in the transaction if an abort occurs that the object never learns about (which is possible). Since the primary purpose of Enterprise Services is to support scalable, transactional business logic in a middle tier, coupling transactions with instance management and other services makes perfect sense.

Yet separating the ability to control transactions from these other services would allow developers more flexibility and more choice. Requiring objects to be stateless just to use distributed transactions can seem a little extreme. Accordingly, System.Transactions doesn't impose this requirement. Instead, this new addition in version 2.0 of the .NET Framework is focused strictly on transactions, imposing no other requirements on an application.

It's important to understand, though, that the increased flexibility provided by System.Transactions also makes it easier for developers (not you, of course, but other developers) to do dumb things, such as allowing an object's in-memory state to differ from what's in the database after a transaction has aborted. Enterprise Services and its predecessors are like controlling parents. They know what's best for youstateless objects for transactional middle-tier logicand so they make you do the right thing. Used intelligently, System.Transactions allows the exact same behavior, but you're no longer forced into it. Instead, Microsoft has decided that you're now a mature, grown-up developer. Doing the right thing is left up to you.


The two methods in this simple class, Deposit and Withdrawal, each begin with the AutoComplete attribute (and since this is just an example, the code for these methods is omitted). This attribute indicates that if the method returns an exception, the serviced component will vote to abort the transaction of which it's a part. If the method completes normally, however, this component will vote to commit the transaction to which it belongs. Note that different attributes are applied at different levels. The Transaction attribute, for example, can be applied only to a classit can't be set per methodwhile AutoComplete can be applied only on a per-method basis. If the developer of this application wished to add a method to check the balance, she might well choose to put this method in some other class. Adding it to the BankAccount class would require the method to use a transaction, which isn't generally necessary for this kind of simple read operation.

Attributes can be used to specify a class's transactional requirements


Many other attributes are available for controlling aspects of a serviced component's behavior. For example, the JustInTime- Activation attribute allows turning just-in-time activation on and off (although this feature is automatically turned on for classes that use transactions), while the ObjectPooling attribute controls whether pooling is used and, if it is, how large the pool will be. Other available attributes set application-wide options such as the name of the application.

Attributes can also be used to specify the use of other services


Enterprise Services and COM+

Unlike most of the .NET Framework, the code that provides COM+ services was not rewritten as managed code. Instead, the classes in System.EnterpriseServices provide a wrapper around the existing implementation that allows managed objects access to these services. In spite of this, serviced components are able to use those services without leaving the managed environment. As Figure 7-5 shows, key COM+ services such as transactions are provided using context information maintained by COM+ itself in unmanaged code. When this context is accessed, such as when a serviced component votes to commit or abort a transaction, that request flows across the boundary between managed and unmanaged code. Interactions among serviced components, however, remain completely within the managed environment provided by the CLR. Since crossing into unmanaged code incurs a slight performance penalty, this ability to remain almost entirely within the managed space is a good thing.

Figure 7-5. COM+ maintains context information for serviced components, allowing it to provide services across the managed/unmanaged boundary.


COM+ has not been completely rewritten as managed code


What's Next: Windows Communication Foundation

In some ways, all of the technologies described in this chapter do the same thing: Let developers build distributed applications. Each one addresses this problem in a slightly different way, and so each has strengths and weaknesses for a particular situation. Still, why have three similar solutions for what is really the same problem? The Microsoft people who control these technologies asked themselves the same question. The answer they came up with was Windows Communication Foundation (WCF).

Part of the WinFX technology suite, WCF effectively combines the functionality of ASP.NET Web Services, .NET Remoting, and Enterprise Services. It also provides a way to use queued messaging via Microsoft Message Queuing (MSMQ), along with a number of other features. Once WCF is available, applications that would have been built on ASP.NET Web Services, .NET Remoting, or Enterprise Services will instead largely be built on this new foundation.

Designed from the start for a world of interoperable Web services, WCF's core protocol is SOAP, although it supports an optimized binary protocol for WCF-only communication as well. WCF implements a full set of the WS-* specifications, allowing secure, reliable, and transactional communication using Web services. WCF also provides a variety of activation options, as in .NET Remoting, allows controlling transactions and other behavior using attributes, as in Enterprise Services, and more. A primary goal of WCF is to support the creation of service-oriented applications, the building blocks of service-oriented architecture (SOA).

While WCF provides the services of the various communication technologies that preceded it, it doesn't provide the same programming interfaces. Except for SOAP, it also doesn't provide the same protocols. A WCF application won't interoperate with a .NET Remoting application, for instance, and porting code from any earlier technologies to WCF will require at least some effort. Applications built using ASP.NET Web services will interoperate with WCF, however, and they'll also be easiest to port to this new foundation. Prior to WCF's release, it makes sense to create applications that use ASP.NET Web Services whenever possible.

WCF represents a big step forward for .NET developers. By rationalizing Microsoft's technologies for creating distributed applications, it lowers the bar for creating modern software. In the very complex world that confronts developers today, this certainly counts as progress.


An important part of standard COM+ is an interface called IObjectContext that contains fundamental methods for components to use. Perhaps the most important of these are SetComplete and SetAbort, the two methods that allow a component to explicitly cast its vote in a transaction. In Enterprise Services, these same methods are available through a class called ContextUtil. If a transactional method wishes to control its commitment behavior directly, it can do so by calling these methods.

The methods in the traditional COM+ IObjectContext interface are still available


Enterprise Services also has a few more artifacts of its foundation in unmanaged code. For example, when a serviced component is accessed remotely, that access relies on DCOM rather than on .NET Remoting. Similarly, serviced components must have entries in the Windows registry, like traditional COM+ components but unlike other .NET classes. These entries can be created and updated automatically by the Enterprise Services infrastructurethere's no need to create them manuallybut requiring them at all betrays this technology's COM foundations.

Remote access to serviced components is via DCOM


Enterprise Services is an important part of the .NET Framework. While it's used by only a minority of applications, the services it provides significantly simplify the lives of the people who create those applications. And while its implementation as a veneer on the old COM+ introduces some messiness, this technology nevertheless succeeds in bringing these essential services into the .NET world.

Enterprise Services is essential to the .NET environment





Understanding. NET
Understanding .NET (2nd Edition)
ISBN: 0321194047
EAN: 2147483647
Year: 2004
Pages: 67

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net