<b>Microsoft's Enterprise Services</b> seems a bit murky and undefined on the surface, but there is more to it than meets the eye. Here are the capabilities that you'll find under the hood, and how they can help you enhance your <b>distributed applications architecture</b>.
Enterprise Services is one of those Microsoft products whose identity is murky at best. Like SharePoint Services, InfoPath and other Microsoft software that doesn't seem entirely focused on a single mission, Enterprise Services tends to get lost in the crowd. Whispers that it is nothing more than warmed-over COM+ don't help. And the serious lack of useful documentation almost serves to give it a reputation as something to avoid.
On the other hand, if you're stuck in client-server space and don't have the budget for the heavy-duty stuff, Enterprise Services can equip you to take the enterprise plunge. Here are some powerful features and tricks that aren't particularly visible to the naked eye.
1. Abstract the layers of your architecture with loosely-coupled events
Enterprise Services inherits a substantial legacy from COM+, including the ability of serviced components to publish events to the COM+ facility. COM+ takes over the task of connecting events to clients, and a layer of abstraction is born.
Loosely-coupled events (LCEs) in Enterprise Services are key building blocks in your multi-tiered environment. Traffic between server(s) and client(s)—that is, published events that clients invoke—is driven by event classes registered with COM+; classes that deliver events to subscribing clients. Connections don't need to be managed from the data source, so your data layer is decoupled; events and clients are dynamically coupled, so you have true enterprise connectivity through your application environment.
2. Optimize your applications, using Enterprise Services concurrency and synchronization features
Enterprise Services synchronization advances the synchronization techniques of COM+, taking you from apartments to activities: synchronization domains that are based on logical threads, rather than physical threads. Physical threads instead form chains that comprise a logical thread, called causalities.
Synchronization domains inherit the TNA (thread-neutral apartment) from COM+; activities leverage the TNA feature of leaving a thread that has entered via a method call even after the method call is done, eliminating a thread switch. Overhead is trimmed because nothing changes but a few TNA variables. If your applications use synchronization domain activities heavily, the overhead savings will be considerable and the environmental performance more optimal.
3. Isolation levels can be configured, allowing you to fine-tune system performance
Maintaining data integrity across transactions is a matter of locking data while it is being used. There are a lot of variables involved in how well this practice works, including the length of time the data is locked, how many users need it, how often it changes, and so on.
This can be controlled through Isolation level. If you're running Enterprise Services on Windows Server 2003, you have control of the Isolation level applied to the locking of data through the Isolation property of the transaction attribute. High isolation levels mean higher data integrity but less concurrency; lower isolation levels increase concurrency but also increase risk to data integrity. The best of all worlds is to find a balance that is right for the application.
4. Manage application states
Enterprise Services enables you to maintain object states in a number of different places, and your design choices in this area can affect your application scalability. Why? Because tracking object state across multiple client calls to an object and then across many objects, can add up to a very significant consumption of resources.
In Enterprise Services, you can manage state at the serviced component level or the client application level, by storing state values at that level. How do you choose which level is appropriate? There are many factors: how fast must state be accessed? How often does it change? Is it linked to users, an application, or multiple applications? Are components load-balanced? Is the object transactional? The point is, Enterprise Services allows you to choose.
You can also, if it makes sense, store state values in a database—useful if, for instance, the state of an application must be restored if your system goes down—or in shared properties (through the Shared Property Manager).
5. Leverage Enterprise Services concurrency and synchronization to enhance quality of data access
The logical thread concept put forth in #2 offers other across-the-board advantages, not the least of which is an overall reduction in lock-out issues—so data issues due to access errors can be dramatically trimmed. Logical threads muster processes into activities, and those processes are actually facilitated by different physical threads. However, since activities themselves are cross-context, cross-process, cross-application, and traffic would get worse, not better, if the traditional approach of locking threads was used. Instead, locks are not used on threads, but activities.
Specifically, an activity assumes a single logical thread, though the synchronization domain itself can encompass many applications, many contexts, many processes, many physical threads—you really can get very creative with it. The restriction of the single logical thread permits you to link the whole thing together and lock it up with a single event, rather than many. If an activity has a lock on a particular object within the domain, then any other activity wanting access to it waits until the causality lock—the lock on the logical thread—is released. One lock, not many, per activity. Object state is therefore no longer a programming concern per se; activities are availed of synchronization objects that a thread locks upon entering. Those synchronization objects are unlocked, and the activity made available to a new logical thread, when the causality lock is released.
6. Reduce code and development time of applications by aliasing components
If you're running Enterprise Services on Windows Server 2003, there's a neat trick you can do in development that will yield a faster, smaller app: you can alias components, configuring a single physical component implementation lots of times.
In COM+, you might develop a component and use it many times, in different instances—only register and configure it once—so to get multiple uses out of it, you must create multiple versions, each with its own constructor. The result is lots of cutting and pasting of code.
In Enterprise Services (on Server 2003), it's much simpler. Since you don't have to re-implement the component, you're cutting down on code; you're essentially recycling the component implementation, and you're doing it at the binary level, which is faster, cheaper, and better.
7. Distribute and manage components over a network
Another COM+ legacy that Enterprise Services leverages is .NET Remoting, which allows events to be sent across your network: "Delegates" are created and events that established parameters and handler method return type for a client. The handler method is implemented and registered with the object event, so the object can remain tied to the client through the event.
You can distribute LCEs (see #1) across multiple systems in a couple of different ways.
LCE routing is subscriber-side networking. Subscribers are defined for both the client system and the system handling the LCE traffic, and COM+ routing is used to do event distribution. (As you might guess, this technique can only be used with persistent subscribers.)
Event-class proxies are another way. You can create a proxy that connects to an event class, since event classes are serviced components. This allows you to network between event classes and publishers.
You can also make the publisher-to-subscriber call asynchronous, passing messages to message queues, with serviced component methods invoked via those messages to buffer the system and further decouple components. This technique can be applied with LCEs and event classes.
8. Create services without components
The serviced component is the star of the Enterprise Services show. The idea is one of those we-enforce-good-design ideas that Microsoft foists upon unsuspecting developers: COM+ is the lightning in the distributed applications bottle, and to leverage COM+, your code has to be registered with component services, via a ServicedComponent class—so that your classes are parsed by service.
If you're running Enterprise Services on Windows 2003, however, life is simpler. Services are applied to a component as a matter of course in a service domain; it is a de facto serviced component, without actually inheriting anything from ServicedComponent.
9. Manage transactions through attributes
One of the major reasons to use Enterprise Services is the automation of transactions, to get away from having to manage transactions in code. Enterprise Services allows you to go in a more efficient direction, managing transactions in attributes.
When you manage transactions in code, you create method arguments that pass transactions. In Enterprise Services, you can have transactions generated by the runtime, and control an object in a class with respect to transactions that apply. The Transaction attribute is applied to classes implementing serviced components, and allows you to context with respect to a transaction, which components participate in a transaction, when a new transaction is created, and so on.
10. Object-bound components are assumed
Object context is used to (among other things) control components with respect to threading and accessibility. Enterprise Services facilitates the creation of context-bound components by virtue of their base class (ServicedComponent) deriving from the class System.ContextBoundObject. You have .NET Remoting context as a matter of course with serviced components. Context simplifies the fine-tuning of components to the process they support, by defining their runtime requirements and compatibilities.