Поделиться через


8 – Updating aExpense to Enterprise Library 6

patterns & practices Developer Center

On this page: Download:
The aExpense Application | The aExpense Architecture | Using Enterprise Library v5.0 | Caching | Logging | Exception Handling | Validation | Security | Policy Injection | Unity | NuGet Packages and References – Before and After | Handling Blocks Removed from Enterprise Library 6 | Replacing Caching Functionality | Replacing the Authorization Rule Provider | Handling Blocks Updated in Enterprise Library 6 | Using the Exception Handling Application Block Version 6 | Using the Validation Application Block Version 6 | Using the Policy Injection Application Block Version 6 | Using Unity Version 3 | Using the New Blocks in Enterprise Library Version 6 | The Semantic Logging Application Block | The Transient Fault Handling Application Block | Other Possible Changes | More Information

Download code

Download PDF

Download Paperback

This chapter describes how the aExpense reference implementation was upgraded from Enterprise Library 5 to Enterprise Library 6. The upgrade process included replacing functionality that was removed from Enterprise Library 6, updating the application to work with the new versions of existing application blocks, and modifying the application to take advantage of some of the new features in Enterprise Library 6. The updated version of aExpense also takes advantage of some of the features in the .NET Framework 4.5, such as caching and the use of claims.

The chapter describes the before and after state of the implementation as it relates to each of the Enterprise Library blocks that aExpense uses. It also highlights any issues encountered, significant changes made, and decisions taken by the team in relation to the update.

The aExpense Application

The aExpense application allows employees at Adatum (a fictional company) to submit, track, and process business expenses. Everyone in Adatum uses this application to request reimbursements.

The application is representative of many other applications in Adatum's portfolio so it's a good test case for upgrading to Enterprise Library 6. The developers at Adatum hope to gain a detailed understanding of what it takes to upgrade an application that uses Enterprise Library 5.0 to Enterprise Library 6 from this project before embarking on similar upgrades to some of the larger, more critical, systems at Adatum.

Dn440722.note(en-us,PandP.60).gifBeth says:
Beth The aExpense application is typical of many LOB applications that use Enterprise Library.

Adatum also upgraded the aExpense application from using version 4 of the .NET Framework to version 4.5 of the .NET Framework as part of the migration project.

The aExpense Architecture

Figure 1 illustrates the architecture of the version of aExpense that uses Enterprise Library 5. The sample application simulates the use of Active Directory. In the version of aExpense that uses Enterprise Library 6, events are logged to file and database tables, not to the Windows Event Log.

Figure 1 - aExpense architecture

Figure 1 - aExpense architecture

The architecture is straightforward and one that many other applications use. aExpense is an ASP.NET application and employees use a browser to interact with it. The application makes use of many of the Enterprise Library 5.0 blocks and uses Unity as a dependency injection container.

Dn440722.note(en-us,PandP.60).gifBeth says:
Beth Like many of Adatum’s applications, the aExpense application uses Enterprise Library and Unity.

The application simulates using Windows authentication for security. To store user preferences, it relies on ASP.NET membership and profile providers. Exceptions and logs are implemented with Enterprise Library's Exception Handling Application Block and Logging Application Block. The website simulates using Directory Services APIs to query for employee data stored in Active Directory, such as the employee's manager. Managers can approve the expenses.

Dn440722.note(en-us,PandP.60).gifJana says:
Jana Adatum’s aExpense application uses a standard website architecture based on ASP.NET with data stored in SQL Server. However, it does integrate with other in-house systems.

The aExpense application implements the trusted subsystem to connect to SQL Server. It authenticates with a Windows domain account. The SQL database uses integrated authentication mode. The aExpense application stores its information on SQL Server.

Using Enterprise Library v5.0

The aExpense application uses many of the application blocks from Enterprise Library 5.0. This section describes, briefly, how and why aExpense uses these blocks before migrating to version 6. You may find it useful to have the version of aExpense that uses Enterprise Library v5.0 open in Visual Studio as you read through this section. This will enable you to explore the application in greater detail.

Caching

The aExpense application makes use of the Caching Application Block in the ExpenseRepository class. It caches expense items when it retrieves them from the backing store to minimize round-trip times on subsequent requests for the same data: you can see this behavior in the GetExpensesForApproval, GetExpensesById, GetExpesnsesByUSer, and UpdateCache methods. The Initialize method in this class reads the configuration file and initializes the cache. The block also encrypts the cache contents.

Dn440722.note(en-us,PandP.60).gifBeth says:
Beth Encrypting the cache contents accounts for the use of the “Enterprise Library 5.0 – Caching Application Block Cryptography Provider” and “Enterprise Library 5.0 – Cryptography Application Block” NuGet packages.

Logging

The aExpense application makes extensive use of the version 5.0 Logging Application Block to write log data to a variety of locations. If you examine the logging configuration in the Web.EnterpriseLibrary.config file, you will see four different listeners defined. One of these listeners is a database trace listener, and this accounts for the use of the version 5.0 “Logging Application Block Database Provider” and “Data Access Application Block” NuGet packages.

Note

The SimulatedLdapProfileStore class also uses a Database instance from the Data Access Application Block.

In the aExpense application, the TracingBehavior class shown below is responsible for writing to the log. This class defines a virtual method interceptor that is configured in the Unity container; you can see how the interceptor is configured in the ContainerBootstrapper class. Notice that this interceptor class is used with the Model.User class.

public class TracingBehavior : IInterceptionBehavior
{
  public IMethodReturn Invoke(IMethodInvocation input,
    GetNextInterceptionBehaviorDelegate getNext)
  {
    if (Logger.IsLoggingEnabled())
      {
        // Only log methods with arguments (bypass getters)
        if (input.Arguments.Count > 0)
        {
          string arguments = string.Join(",", input.Arguments.OfType<object>());
          Logger.Write(string.Format(
            CultureInfo.InvariantCulture,
            "{0}: Method {1}.{2} executed. Arguments: {3}",
            DateTime.Now,
            input.MethodBase.DeclaringType.Name,
            input.MethodBase.Name,
            arguments), Constants.ExpenseTracingCategory,
            Constants.TracingBehaviorPriority);
        }
      }
 
      return getNext()(input, getNext);
  }
 
  public IEnumerable<Type> GetRequiredInterfaces()
  {
    return Enumerable.Empty<Type>();
  }
 
  public bool WillExecute
  {
    get { return true; }
  }
}

You can see the messages written by this behavior in the Logging database in the Log table. For example:

“04/18/2013 11:27:41: Method User.set_UserName executed”

Exception Handling

The configuration of the Exception Handling Application Block defines two exception policies: “Notify Policy” and “Global Policy.” Both of these policies make use of the Exception Handling Application Block Logging Handler to write details of any exceptions to the logging database.

You can see examples of the Exception Handling block in use in the ExpenseRepository and Global classes.

Validation

The aExpense application uses the Validation Application Block attributes in the model classes Expense and ExpenseItem to enforce validating the properties defined in these classes. You can also see the “Validation Application Block Integration with ASP.NET” NuGet package in use in the AddExpense.aspx file: Look for the <cc1:PropertyProxyValidator> tags.

The application uses two custom validators. The ApproverValidator class validates the approver name in the Expense class, and the DuplicateExpenseDetailsValidator class is part of the ExpenseRulset defined in the configuration file.

Security

The aExpense application uses the Authorization Rule Provider from the version 5.0 Security Application Block to determine whether the current user is authorized to approve an expense. The UpdateApproved method in the ExpenseRepository class is decorated with the custom RulesPrincipalPermission attribute. This attribute class uses the RulesPrincipalPermission class, which in turn reads the authorization rule from the configuration file.

Policy Injection

The aExpense application uses policy injection to log saving expenses in the ExpenseRepository class. The SaveExpense method has an attribute Tag(“SaveExpensePolicyRule”). The configuration file contains the policy definition, which is shown below.

<policyInjection>
  <policies>
    <add name="ExpenseRepositoryTracingPolicy">
      <matchingRules>
        <add name="TagRule" match="SaveExpensePolicyRule"
         ignoreCase="false"
         type="Microsoft.Practices.EnterpriseLibrary.PolicyInjection
               .MatchingRules.TagAttributeMatchingRule, ..."/>
      </matchingRules>        
      <handlers>
        <add type="Microsoft.Practices.EnterpriseLibrary.Logging
                   .PolicyInjection.LogCallHandler, ..."
          logBehavior="After"
          beforeMessage="Before invoking"
          afterMessage="After invoking"
          name="Logging Call Handler">
          <categories>
            <add name="ExpenseTracing" />
          </categories>
        </add>
      </handlers>
    </add>
  </policies>
</policyInjection>

You can see log entries created by the Logging Call Handler in the Logging database in the Log table by searching for log entries with a title “Call Logging.”

Unity

The ContainerBootstrapper class includes the following code.

container
    .AddNewExtension<EnterpriseLibraryCoreExtension>()
    .RegisterType<IProfileStore, SimulatedLdapProfileStore>(
      new ContainerControlledLifetimeManager())
    .RegisterType<IUserRepository, UserRepository>(
      new ContainerControlledLifetimeManager())
    .RegisterType<AExpense.Model.User>(
      new Interceptor<VirtualMethodInterceptor>(),
      new InterceptionBehavior<TracingBehavior>())
    .RegisterType<IExpenseRepository, ExpenseRepository>(
      new ContainerControlledLifetimeManager(),
      new Interceptor<VirtualMethodInterceptor>(),
      new InterceptionBehavior<PolicyInjectionBehavior>());
 
UnityServiceLocator locator = new UnityServiceLocator(container);
ServiceLocator.SetLocatorProvider(() => locator);

This code adds the Enterprise Library extension to the container that enables you to resolve types defined in the Enterprise Library blocks in your code. It also registers a number of application types and configures the Unity service locator.

The Approve page class uses the Dependency attribute to indicate that an IExpenseRepository instance should be injected into the instance. This BuildUp method performs this injection in the Application_PreRequestHandlerExecute method in the Global class as shown in the following code sample.

protected void Application_PreRequestHandlerExecute(object sender, EventArgs e)
{
    ...
 
    Page handler = HttpContext.Current.Handler as Page;
    if (handler != null)
    {
        IUnityContainer container = Application.GetContainer();
        container.BuildUp(handler.GetType(), handler);
    }
}

NuGet Packages and References – Before and After

As an overview of how aExpense uses Enterprise Library 5.0 before the update, the following table lists the Enterprise Library NuGet packages and related references in the aExpense application.

NuGet package

References

Unity

(version 2.1)

Microsoft.Practices.Unity

Microsoft.Practices.Unity.Configuration

Unity Interception Extension

(version 2.1)

Microsoft.Practices.Unity.Interception

Microsoft.Practices.Unity.Interception.Configuration

CommonServiceLocator

Microsoft.Practices.ServiceLocation

Enterprise Library 5.0 – Common Infrastructure

Microsoft.Practices.EnterpriseLibrary.Common

Enterprise Library 5.0 – Caching Application Block

Microsoft.Practices.EnterpriseLibrary.Caching

Enterprise Library 5.0 – Caching Application Block Cryptography Provider

Microsoft.Practices.EnterpriseLibrary.Caching.Cryptography

Enterprise Library 5.0 – Cryptography Application Block

Microsoft.Practices.EnterpriseLibrary.Security.Cryptography

Enterprise Library 5.0 – Data Access Application Block

Microsoft.Practices.EnterpriseLibrary.Data

Enterprise Library 5.0 – Exception Handling Application Block

Microsoft.Practices.EnterpriseLibrary.ExceptionHandling

Enterprise Library 5.0 – Exception Handling Application Block Logging Handler

Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Logging

Enterprise Library 5.0 – Logging Application Block

Microsoft.Practices.EnterpriseLibrary.Logging

Enterprise Library 5.0 – Logging Application Block Database Provider

Microsoft.Practices.EnterpriseLibrary.Logging.Database

Enterprise Library 5.0 – Policy Injection Application Block

Microsoft.Practices.EnterpriseLibrary.PolicyInjection

Enterprise Library 5.0 – Security Application Block

Microsoft.Practices.EnterpriseLibrary.Security

Enterprise Library 5.0 – Validation Application Block

Microsoft.Practices.EnterpriseLibrary.Validation

Enterprise Library 5.0 – Validation Application Block Integration with ASP.NET

Microsoft.Practices.EnterpriseLibrary.Validation.Integration.AspNet

The following table shows the NuGet packages and references used in the aExpense application after the update.

NuGet Packages

References

Unity

(version 3)

Microsoft.Practices.Unity

Microsoft.Practices.Unity.Configuration

Unity Interception Extension

(version 3)

Microsoft.Practices.Unity.Interception

Microsoft.Practices.Unity.Interception.Configuration

CommonServiceLocator

Microsoft.Practices.ServiceLocation

Enterprise Library 6 – Data Access Application Block

Microsoft.Practices.EnterpriseLibrary.Data

Enterprise Library 6 – Exception Handling Application Block

Microsoft.Practices.EnterpriseLibrary.ExceptionHandling

Enterprise Library 6 – Policy Injection Application Block

Microsoft.Practices.EnterpriseLibrary.PolicyInjection

Enterprise Library 6 – Semantic Logging Application Block (version 1.0)

Microsoft.Practices.EnterpriseLibrary.SemanticLogging

Enterprise Library 6 – Semantic Logging Application Block – SQL Server Sink (version 1.0)

Microsoft.Practices.EnterpriseLibrary.SemanticLogging.Database

Enterprise Library 6 – Transient Fault Handling Application Block

Microsoft.Practices.EnterpriseLibrary.TransientFaultHandling

Microsoft.Practices.EnterpriseLibrary.TransientFaultHandling.Configuration

Enterprise Library 6 – Transient Fault Handling Application Block – Microsoft Azure SQL Database integration

Microsoft.Practices.EnterpriseLibrary.TransientFaultHandling.Data

Enterprise Library 6 – Validation Application Block

Microsoft.Practices.EnterpriseLibrary.Validation

Enterprise Library 6 – Validation Application Block Integration with ASP.NET

Microsoft.Practices.EnterpriseLibrary.Validation.Integration.AspNet

Dn440722.note(en-us,PandP.60).gifBeth says:
Beth You can use the PowerShell script, Update-EntlibConfiguration.ps1, to update the version numbers in all of the configuration files in your project. It also updates any changed namespaces in the configuration files. You can find this script in the [Solution Folder]\packages\EnterpriseLibrary.Common.[Version] folder after you install an Enterprise Library 6 NuGet package.

Handling Blocks Removed from Enterprise Library 6

The version of aExpense that uses the Enterprise Library 5.0 blocks uses both the Caching Application Block and the Security Application Block, neither of which are part of Enterprise Library 6. The developers at Adatum had to replace the functionality used from these blocks in the latest version of the aExpense application.

Replacing Caching Functionality

In the new version of aExpense that uses Enterprise Library 6, classes in the System.Runtime.Caching namespace provide the caching functionality for the ExpenseRepository class. The changes to the GetExpensesForApproval, GetExpensesById, GetExpesnsesByUSer, and UpdateCache methods which access the cache are minimal. The Initialize method now configures the cache using a cache instance from the System.Runtime.Caching namespace.

Note

To make it easier to install, the aExpense RI currently uses an in-memory caching solution that does not support distributed caching scenarios such as web farm deployments. For a distributed caching solution, you should consider using AppFabric for Windows Server, which requires minimal code changes in the application. For more information, see "AppFabric Caching API Usage Sample" on MSDN.

Replacing the Authorization Rule Provider

The new version of aExpense now uses claims-based authorization to determine role membership. The UpdateApproved method in the ExpenseRepository class is now decorated with the ClaimsPrincipalPermission attribute. aExpense also authorizes page access through settings on the claimsAuthorizationManager section of the configuration file.

Dn440722.note(en-us,PandP.60).gifPoe says:
Poe
The RI shows a very basic implementation of claims based authorization. You can read more about claims-based authentication and authorization in the guide "A Guide to Claims-Based Identity and Access Control (2nd Edition)" available for download from MSDN.

Handling Blocks Updated in Enterprise Library 6

The version of aExpense that uses Enterprise Library 6, continues to use the Exception Handling Application Block, the Validation Application Block, the Policy Injection Application Block, and Unity. There are some changes in the way that aExpense configures and uses these blocks that are discussed in this section.

Using the Exception Handling Application Block Version 6

The major change in the use of the Exception Handling block is due to a change in the logging approach used by aExpense; it now uses the Semantic Logging Application Block in place of the Logging Application Block. This change is discussed later in this chapter. You can see the impact of this in the Web.EnterpriseLibrary.config file in the exceptionHandlingSection where the old "Logging Exception Handler" has been replaced with a custom "SemanticLogging Exception Handler" definition.

There are also changes in the ContainerBootstrapper class that relate to the Exception Handling Application Block because the ExceptionManager type is not registered to the Unity container automatically. These changes are described in detail in the section covering Unity later in this chapter.

The version numbers in the configuration file have been updated to reflect the new Enterprise Library version.

Both versions of the aExpense application resolve the ExceptionManager type from the container in the ExpenseRepository and UserRepository classes in the same way. However, because version 6 of the block does not automatically configure the static ExceptionPolicy class, the developers at Adatum chose to modify the Global class to resolve the ExceptionManager type from the container used throughout the application as shown in the following code sample.

protected void Application_Start(object sender, EventArgs e)
{
    ...
 
    IUnityContainer container = new UnityContainer();            
    ContainerBootstrapper.Configure(container);
 

    Application.SetContainer(container);
 
    ...
}

private void Application_Error(object sender, EventArgs e)
{
    Exception ex = Server.GetLastError();
    ...
    var exceptionManager = Application.GetContainer().Resolve<ExceptionManager>();
    if (exceptionManager != null)
    {
        exceptionManager.HandleException(ex, Constants.GlobalPolicy);
    }
}

Using the Validation Application Block Version 6

There are no changes in the way that the aExpense application uses the Validation Application Block. All of the existing validation is done either using attributes or using the "Validation Application Block Integration with ASP.NET" NuGet package and tags in the .aspx files.

Using the Policy Injection Application Block Version 6

The ContainerBootstrapper class now includes code to load the Policy Injection Block settings from the configuration file and use them to configure the container. Previously, in Enterprise Library 5.0, this happened automatically. The following code sample shows how to do this in version 6.

var policyInjectionSettings = (PolicyInjectionSettings)source.
GetSection(PolicyInjectionSettings.SectionName);
policyInjectionSettings.ConfigureContainer(container);

The aExpense solution that uses Enterprise Library 5.0 used the logging call handler that was included with Enterprise Library. However, the aExpense solution that uses Enterprise Library 6 uses the Semantic Logging Application Block in place of the Logging Application Block. It therefore includes a custom call handler for semantic logging. You can see the updated configuration for the block in the Web.EnterpriseLibrary.config file. The following code sample shows the custom SemanticLogCallHandler class included in the solution that handles logging for the expense tracing policy.

[ConfigurationElementType(typeof(CustomCallHandlerData))]
public class SemanticLogCallHandler : ICallHandler
{
    public SemanticLogCallHandler(NameValueCollection attributes)
    {
    }
 
    public IMethodReturn Invoke(IMethodInvocation input,
      GetNextHandlerDelegate getNext)
    {
        if (getNext == null) throw new ArgumentNullException("getNext");
 
        AExpenseEvents.Log.LogCallHandlerPreInvoke(
          input.MethodBase.DeclaringType.FullName,
          input.MethodBase.Name);
 
        var sw = Stopwatch.StartNew();
 
        IMethodReturn result = getNext()(input, getNext);
 
        AExpenseEvents.Log.LogCallHandlerPostInvoke(
          input.MethodBase.DeclaringType.FullName,
          input.MethodBase.Name, sw.ElapsedMilliseconds);
 
        return result;
    }
 
    public int Order { get; set; }
}

Using Unity Version 3

To simplify the registration types in the Unity container, the developers at Adatum replaced the individual registrations of the ExpenseRepository, SimulatedLdapProfileStore, and UserRepository types with the following code in the ContainerBootStrapper class.

container.RegisterTypes(
  AllClasses.FromAssemblies(Assembly.GetExecutingAssembly()), 
  WithMappings.FromAllInterfacesInSameAssembly, 
  WithName.Default, 
  WithLifetime.ContainerControlled);

This approach, using the new registration by convention feature in Unity, provides minimal benefits in this scenario because the application currently only registers three types. However, as the application grows and becomes more complex this approach becomes more useful.

The Enterprise Library blocks no longer have a dependency on Unity, and in consequence, they no longer bootstrap a Unity container automatically. The aExpense solution that uses Enterprise Library 5.0 includes the following code to register the blocks and configure them based on the configuration data in the configuration file.

container
  .AddNewExtension<EnterpriseLibraryCoreExtension>();

To minimize the changes in the aExpense solution that uses Enterprise Library 6, the developers at Adatum chose to register the blocks the application uses manually in the container as shown in the following code sample. In this way, the developers don’t have to make any changes elsewhere in the application where the Enterprise Library types are resolved.

IConfigurationSource source = ConfigurationSourceFactory.Create();
 
var policyInjectionSettings = (PolicyInjectionSettings)source
  .GetSection(PolicyInjectionSettings.SectionName);
policyInjectionSettings.ConfigureContainer(container);
 
var policyFactory = new ExceptionPolicyFactory(source);
var dbFactory = new DatabaseProviderFactory(source);
var validationFactory = 
  ConfigurationValidatorFactory.FromConfigurationSource(source);

 
container
  .RegisterType<ExceptionManager>(
    new InjectionFactory(c => policyFactory.CreateManager()))
  .RegisterType<Database>(
    new InjectionFactory(c => dbFactory.CreateDefault()))
    .RegisterInstance<ValidatorFactory>(validationFactory);
Dn440722.note(en-us,PandP.60).gifJana says:
Jana You don’t need to register the Enterprise Library types with the container, you can always use the factories to instantiate the objects directly. However, because the aExpense application was originally designed with Enterprise Library 5.0 in mind, it resolves the Enterprise Library types from the container in many places throughout the application, so registering the necessary types resulted in fewer changes, and all the changes are centralized in the ContainerBootstrapper class.

Using the New Blocks in Enterprise Library Version 6

The new version of the aExpense application uses both new Enterprise Library 6 blocks: the Semantic Logging Application Block, and the Transient Fault Handling Application Block. The developers at Adatum decided to replace the existing logging in the application that was based on the Logging Application Block with the Semantic Logging Application Block in order to gain some of the benefits associated with this logging approach. They added the Transient Fault Handling Application Block: this is a first step to prepare the application for using SQL Database running in the cloud in place of the existing on-premises database solution.

The Semantic Logging Application Block

The Semantic Logging Application Block enables Adatum to collect semantic/structured logging information from the aExpense application. Structured log information will enable support staff to query and analyze the log data collected from the aExpense application. If Adatum chooses to host the Semantic Logging Application Block in a separate Windows service, Adatum can make the logging process more robust: a major failure in the aExpense application is less likely to lose logging data at the time the crash occurs, making troubleshooting more effective in analyzing the cause of the problem.

The new version of the aExpense application includes the AExpenseEvents class that derives from the EventSource class in the System.Diagnostics.Tracing namespace. This class defines all of the messages that the aExpense application can generate. It also defines various pieces of metadata associated with trace messages such as keywords, opcodes, and tasks. The application can generate a trace message by invoking any of the message methods in this class. For example, the SaveExpense method in the ExpenseRepository class records when a save operation begins and ends as shown in the following code sample.

public virtual void SaveExpense(Model.Expense expense)
{
    exManager.Process(() =>
    {
        AExpenseEvents.Log.SaveExpenseStarted(expense.Id, expense.Title);
        ProcessInContext((db) =>
        {
            ...
        });
 
        ...
        AExpenseEvents.Log.SaveExpenseFinished(expense.Id, expense.Title);
    },
    ...);
}
Dn440722.note(en-us,PandP.60).gifMarkus says:
Markus Notice how the calling code doesn’t need to provide information such as the log level or category. That’s all defined in the custom EventSource class.

By default, the aExpense application uses the Semantic Logging Application Block in the in-process mode. If you want to use the Semantic Logging Application Block in its out-of-process mode, you must install and configure the “Enterprise Library Semantic Logging Service” host to collect, filter, and save the log messages from aExpense. The Visual Studio solution includes a folder containing a configuration file (SemanticLogging-svc.xml) for the service and a readme file describing how to set it up.

The service configuration file defines the following sinks for log messages:

  • DataAccess. A flat file destination that receives all log messages tagged with the DataAccess keyword in the AExpense class.
  • UserInterface. A rolling flat file destination that receives all log messages tagged with the UserInterface keyword and a severity of Informational or higher in the AExpense class.
  • SQL-All. A SQL Server database destination that receives all log messages.

The Transient Fault Handling Application Block

Although the aExpense application currently uses an on premises SQL Server solution, Adatum plans to migrate the application’s data to SQL Database running in the cloud. In preparation for this migration, the developers at Adatum added code to the solution to manage retries for the transient errors than can occur when accessing SQL Database.

Note

The SQL detection strategy in the Transient Fault Handling Application Block targets SQL Database running in the cloud rather than SQL Server running on premises. When Adatum changes the connection strings in the application to connect the application to the cloud-based SQL Database, the retry policies will add greater resilience to the calls to the database.

The retry configuration is stored in the Web.EnterpriseLibrary.config file along with the other Enterprise Library block configuration data and defines a single exponential back off policy. As with the other blocks, the ContainerBootstrapper class contains code to load this configuration data and initialize the factory as shown in the following code sample.

var retryPolicySettings = 
  RetryPolicyConfigurationSettings.GetRetryPolicySettings(source);
RetryPolicyFactory.SetRetryManager(
  retryPolicySettings.BuildRetryManager(), throwIfSet: false);
Dn440722.note(en-us,PandP.60).gifCarlos says:
Carlos Although the code to initialize the RetryPolicyFactory object is in the ContainerBootstrapper class, it is not using Unity. There is no preexisting code that resolves retry policies from the container; therefore, the developers chose to use the static facades in the block.

The aExpense application uses the retry policy in the ExpenseRepository and SimulatedLdapProfileStore classes to wrap the calls to the database. The following is an example from the ExpenseRepository class.

private void Initialize(...)
{
  ...
  this.retryPolicy = RetryPolicyFactory
   .GetRetryPolicy<SqlDatabaseTransientErrorDetectionStrategy>();
}

Public virtual void SaveExpense(Model.Expense expense)
{
 ...
 
   this.retryPolicy.ExecuteAction(() => db.SubmitChanges());
 ...
}

Other Possible Changes

The changes illustrated in these two versions of the aExpense application represent the basic changes the developers at Adatum needed to make to migrate the application to Enterprise Library 6, the replacement of the Logging Application Block with the Semantic Logging Application Block, and the introduction of the Transient Fault Handling Application Block. There are additional changes that could be introduced to realize some additional benefits from Enterprise Library 6 such as:

  • Use programmatic configuration in place of declarative configuration. Many of the settings in the configuration file do not need to be changed after the application is deployed: by moving them to programmatic configuration, they would no longer be exposed.
  • Increased use of static facades. Adatum chose to register types from the Database Access Application Block, the Exception Handling Application Block, and Validation Application Block in the Unity container in order to minimize the impact of the migration in other areas of the application. As an alternative, Adatum could follow the pattern adopted by the Transient Fault Handing Application Block and use static facades instead.

More Information

All links in this book are accessible from the book's online bibliography on MSDN at https://aka.ms/el6biblio.

For more information about Unity, see the Dependency Injection with Unity guide. This guide is also available on MSDN: Developer's Guide to Dependency Injection Using Unity.

For more information about migrating to Enterprise Library 6, see the Migration Guide.

For more information on distributed caching solutions, see "AppFabric Caching API Usage Sample" on MSDN.

You can read more about claims-based authentication and authorization in the guide "A Guide to Claims-Based Identity and Access Control (2nd Edition)" available for download from MSDN.

General Links:

Next Topic | Previous Topic | Home | Community