for RuBoard |
After the connection string is specified, it should be securely stored somewhere rather than hard-coded directly in the application. Obviously, storing the connection string enables you to more easily change it as you move from development to test to production. Although there are obviously plenty of options, the second part of this section focuses on the two most common scenarios where connection strings may be stored.
As you'll learn about in more detail on Day 17, "ADO.NET in the Data Services Tier," a serviced component is one that is derived from the ServicedComponent class of the System.EnterpriseServices namespace. As a result, a serviced component can access the run-time services provided by COM+ (Component Services) such as just-in-time (JIT) activation, distributed transactions, object pooling, loosely coupled events, and queued components, among others. |
Note
See Chapter 9 of my book Building Distributed Applications with Visual Basic .NET , published by Sams, for more information on serviced components and Component Services and .NET.
Related to connection strings, the most interesting aspect of COM+ is its object construction feature. In a nutshell , object construction is analogous to specifying command-line parameters for a COM+ component. In other words, you can declaratively specify a string that will be passed into the component when it's instantiated by COM+. The way this works is that the COM+ runtime tests for the presence of an interface called IObjectConstruct when the component is instantiated. If the interface is found, it calls its Construct method and passes in the string. The IObjectConstruct interface is a COM interface and is implemented by the ServicedComponent class, which then exposes its Construct method as a protected virtual ( Overridable in VB .NET) method. This allows classes derived from ServicedComponent to simply override the method to catch the construction string. Listing 9.2 shows an example of a serviced component class that contains the bare minimum to use object construction.
using System.EnterpriseServices; namespace ComputeBooks.Data { [ConstructionEnabled( Default="server=ssosa;Initial Catalog=computebooks;trusted_connection=yes")] public class ComputeBooksStore : ServicedComponent { private string _connect; public string ConstructString { //returns the connection string get { return _connect; } } protected override void Construct(string s) { // called each time an instance of this class is created _connect = s; } // other methods here } }
You'll notice in Listing 9.2 that the ComputeBooksStore class is derived from ServicedComponent and that it contains a private string called _connect . This private variable is assigned the string passed into the overridden Construct method. The connection string is then made available to descendant classes or clients through the public read-only ConstructString property. |
You'll also notice that the class is decorated with the ConstructionEnabled attribute. The presence of this attribute enables object construction when the serviced component is registered in a COM+ application. The Default property specifies the default construction string that will be used if it's not overridden in the Component Services administrative user interface. Of course, both enabling construction and setting the construction string can be performed administratively by right-clicking on the component in the Component Services snap-in (found in the Administrative Tools group ) and selecting Properties. The construction settings can be found on the Activation tab.
Note
Object construction applies to an entire component (that is, a class in .NET). This implies that all methods in the class will use the same connection string ”a point you'll need to consider when designing your classes.
Because object construction is a service that you might want to implement in many serviced component classes, it makes sense to include it in a base class. On Day 17, you'll take a look at an abstract base class that abstracts features such as object construction and pooling for serviced components.
COM+ 1.5 and Aliasing
|
Of course, object construction is an option only if your components are serviced components running in COM+. In many cases, your components that use providers will be accessed directly from ASP.NET pages or from classes instantiated by ASP.NET pages. In these cases, it makes sense to place the connection string with the other configuration information for the application.
Each ASP.NET application includes a file called Web.config in its virtual directory. This file is a simple XML file that contains settings that allow the ASP.NET runtime to make decisions about how the request is to be processed. Basically, it extends the default processing instructions stored in the Machine.config file found in the .NET Framework installation directory. Examples of the information included in Web.config include the authorization and impersonation scheme to use, which class (referred to as an HTTP Handler) will handle the request, and whether the request should be processed by an HTTP module.
In addition to the processing instructions, the Web.config file can contain an element called appSettings into which you can place application-specific information in name-value pairs using an add element, as shown in Listing 9.3.
<?xml version="1.0" encoding="utf-8" ?> <configuration> <appSettings> <add key="SQLConnect" value="data source=ssosa; initial catalog=ComputeBooks;user id=user;pooling=true" /> </appSettings> </configuration>
In Listing 9.3, the appSettings collection contains one element, called SQLConnect, which contains the connection string. A class in your application can then access this value using the static ( Shared in VB .NET) AppSettings property of the ConfigurationSettings class like so:
using System.Configuration; protected void cmdLogin_Click(System.Object sender, _ System.EventArgs e); { ComputeBooksStore store = new ComputeBooksStore( ConfigurationSettings.AppSettings["SQLConnect"].ToString()); }
In this case, you'll notice from the using statement that the ConfigurationSettings class can be found in the System.Configuration namespace. The particular name-value pair is then accessed by passing the key value (or the index) to the AppSettings prop-erty, which exposes a NameValueCollection object that stores the data as a sorted collection of strings. The ComputeBooksStore class then accepts the connection string through its constructor as shown in Listing 9.4.
public class ComputeBooksStore { private string _connect; public string ConnectString { //returns the connection string get { return _connect; } } public ComputeBooksStores(string connect) { _connect = connect; } // other methods here }
Tip
Although it might seem attractive to do so, you can't use a constructor that accepts connection strings with serviced components. Because COM+ doesn't support parameterized construction, serviced components must expose an empty (default) constructor.
To more generically retrieve configuration information, you can use the static GetConfig method of either the ConfigurationSettings class or the HttpContext class as exposed through the Context property of the ASP.NET Page class like so:
System.Object o = Context.GetConfig("appSettings"); ComputeBooksStore store = new ComputeBooksStore(o["SQLConnect"].ToString());
Note
Because configuration files are encoded as XML, they are case sensitive. In the previous example, passing the value of "AppSettings" rather than "appSettings" would result in an unhandled exception.
Although each directory in an ASP.NET application can contain its own Web.config file, the files are processed hierarchically. Therefore, as long as the Web.config file in the root directory of the site contains the appSettings element, code in any subdirectories of the site will be able to access it.
This configuration system is, of course, also available to other .NET applications, such as Windows Forms applications. These applications can include their own configuration file, named appname . exe.config, in the application directory. The runtime will refer to it when the application is loaded. It can contain the same appSettings element in the root configuration element, as shown previously.
for RuBoard |