8 – Updating aExpense to Enterprise Library 6
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 |
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.
Beth says: | |
---|---|
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
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.
Beth says: | |
---|---|
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.
Jana says: | |
---|---|
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.
Beth says: | |
---|---|
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 |
Beth says: | |
---|---|
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.
Poe says: | |
---|---|
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);
Jana says: | |
---|---|
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);
},
...);
}
Markus says: | |
---|---|
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);
Carlos says: | |
---|---|
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:
- There are resources to help if you're getting started with Enterprise Library, and there's help for existing users as well (such as the breaking changes and migration information for previous versions) available on the Enterprise Library Community Site at https://www.codeplex.com/entlib/.
- For more details about the Enterprise Library Application Blocks, see the Enterprise Library Reference Documentation and the Enterprise Library 6 Class Library.
- You can download and work through the Hands-On Labs for Enterprise Library, which are available at https://aka.ms/el6hols.
- You can download the Enterprise Library binaries, source code, Reference Implementation, or QuickStarts from the Microsoft Download Center at https://go.microsoft.com/fwlink/p/?LinkID=290898.
- To help you understand how you can use Enterprise Library application blocks, we provide a series of simple example applications that you can run and examine. To obtain the example applications, go to https://go.microsoft.com/fwlink/p/?LinkID=304210.