Unobtrusive transient fault handling in Azure SQL Database with Entity Framework, Linq To Sql, NHibernate and ADO.NET

It’s fairly well known know that when connecting to an Azure SQL Database you need to protect your application from transient errors that occur when using it.

Luckily, Microsoft provide a library that takes care of most of the effort of detecting these errors and retrying your operations according to a retry policy.

The problem with this library is that most of the documentation out there tells you to essentially wrap every database call in your system in a retry call using the library. Let’s be honest – this is a crappy solution to the problem, particularly for legacy code bases where this might result in a major set of changes to the codebase.

Luckily, there is a way around it:

  • If you are using Entity Framework 6 then check out the new Connection Resiliency functionality, although note that the default implementation doesn’t retry for timeout errors (see the documentation of the below mentioned libraries to see why you might care about that)
  • If you are using NHibernate then you can use the library I’ve previously announced/released; NHibernate.SqlAzure
  • If you are using EntityFramework then the best unobtrusive solutions on the net previously have retries for connection establishment (that have other potential connection management side-effects) and save operations, but not command retries – I’d like to announce the release of a library I have created called ReliableDbProvider that solves these problems in an unobtrusive way (generally you will only need to change your config and possibly one or two lines of code)
  • If you are using ADO.NET (provided you use the Db Provider functionality for managing connections and commands) or Linq To Sql then the ReliableDbProvider library can be used as well

Simulating transient errors when using Azure SQL Database

I recently gave a presentation on the ins and outs of using Azure SQL for the Perth Ms Cloud User Group on Azure SQL Database. If you are curious feel free to check out the presentation file at: https://github.com/robdmoore/SQLAzurePresentation

One of the things I did for the presentation was come up with a demo that illustrated the need for, and impact of, having transient error protection when talking to an Azure SQL Database. I have taken this code and cleaned it up a bit and released it on Github at: https://github.com/robdmoore/SQLAzureTransientDemo

This code is quite unique since I have managed to find a way to reliably elicit the transient exceptions (something I haven’t seen anywhere else on the net). If you need to test some code that needs these exceptions to happen to run and you want to be really sure the code works then feel free to check out the code.

Windows Azure Web Sites Programmatic Web Deploy

I was setting up a continuous integration / deployment pipeline last night for my team at GovHack Perth and I had a lot of trouble getting the web deploy deployment working against an Azure Web Sites site.

I had downloaded the .publishsettings file and copied out the username, password and server to pass through to the .cmd file that is generated by MSBuild when creating a web deploy package. I do this because I create the package separately as part of the CI build and attach it as a build artifact and then separately do the deployment with msdeploy as another CI build step.

The problem I came across was that I kept getting the following error when running the deployment:

C:\Path\To\Project\obj\Release\Package>projectname.deploy.cmd /T /M:https://waws-prod-hk1-001.pu
blish.azurewebsites.windows.net:443/msdeploy.axd /U:$sitename /P:password /A:Basic
SetParameters from:
"C:\Path\To\Project\obj\Release\Package\projectname.SetParameters.xml"
You can change IIS Application Name, Physical path, connectionString
or other deploy parameters in the above file.
-------------------------------------------------------
Start executing msdeploy.exe
-------------------------------------------------------
"C:\Program Files\IIS\Microsoft Web Deploy V3\msdeploy.exe" -source:package='C:
\Path\To\Project\obj\Release\Package\projectname.zip' -dest:auto,computerName="https://waws-prod
-hk1-001.publish.azurewebsites.windows.net:443/msdeploy.axd",userName="$sitename"
,password="password",authtyp
e="Basic",includeAcls="False" -verb:sync -disableLink:AppPoolExtension -disableL
ink:ContentExtension -disableLink:CertificateExtension -setParamFile:"C:\Path\To\Project\obj
\Release\Package\projectname.SetParameters.xml" -whatif
Info: Using ID '744a18b1-51c2-4d05-a674-6c407a7f80c5' for connections to the rem
ote server.
Error Code: ERROR_USER_UNAUTHORIZED
More Information: Connected to the remote computer ("waws-prod-hk1-001.publish.a
zurewebsites.windows.net") using the Web Management Service, but could not autho
rize. Make sure that you are using the correct user name and password, that the
site you are connecting to exists, and that the credentials represent a user who
has permissions to access the site. Learn more at: http://go.microsoft.com/fwl
ink/?LinkId=221672#ERROR_USER_UNAUTHORIZED.
Error: The remote server returned an error: (401) Unauthorized.
Error count: 1.

It turns out the problem was I needed to include the ?site=sitename parameter in the msdeploy destination otherwise (I assume) the load balancer on the publish server can’t authenticate your username and password properly. This meant I needed to switch to using msdeploy.exe directly like so:

"C:\Program Files\IIS\Microsoft Web Deploy V3\msdeploy.exe" -source:package='projectname.zip' -dest:auto,computerName="https://waws-prod-hk1-001.publish.azurewebsites.windows.net:443/msdeploy.axd?site=sitename",userName="$sitename",password="password",authtype="Basic",includeAcls="False" -verb:sync -disableLink:AppPoolExtension -disableLink:ContentExtension -disableLink:CertificateExtension -setParamFile:"projectname.SetParameters.xml"

Hopefully this post helps other people stuck in the same situation (I couldn’t find anything on Google to help with this)!

Announcing NTestDataBuilder library

Further to the blog post I posted yesterday about the approach to generating test fixture data for automated tests that my team has adopted I have open sourced a base class and other supporting code infrastructure to quickly, tersely and maintainably generate fixture data in a consistent way.

I have released this library to GitHub and NuGet under the name NTestDataBuilder.

The GitHub page has a bunch of code snippets that will get you started quickly. Read my previous blog post to get a feel for how I use the code and in particular how I combine the approach with the Object Mother pattern for best effect.

Enjoy!

Test Data Generation the right way: Object Mother + Test Data Builders + NSubstitute + NBuilder

Generating test data for automated testing is an area that I have noticed can get very, very tedious when your application gets more and more complex. More importantly, it’s an area that I have noticed results in hard-to-maintain test logic. If you are a proponent of treating test code with the same importance of production code like I am, then you will want to refactor your test logic to make it more simple, maintainable and DRY.

In my last two projects I have been working with my team to come up with a good solution for this problem and I’m pretty stoked with what we’ve got so far. While I certainly had my hand in the end result, I certainly can’t claim all of the credit – far from it! Big props to my team mates Matt Kocaj and Poya Manouchehri for significant contributions to this.

Newing up objects everywhere

If you organically grow your automated test suite without thinking about how you are generating your test data then it’s likely you will end up with a lot of tests that have arrange sections full of object instantiation, and these sections are likely to get more and more complex as your object model gets complex (what if you need to have a customer that has 3 orders, each with 3 products?).

If you are diligent with refactoring your tests then you will likely start pulling out common instantiations to private methods (or similar), but even then you are likely to notice the following patterns start to emerge:

  • If you need to change the constructor of one of your classes there will be many, many instantiations using that constructor across your test project and so that refactor becomes a pain (and you are likely to do hacks like add default values that you wouldn’t otherwise when adding new parameters to make it easier).
  • There is likely to be a lot of repetition across different test classes in the objects that are created.
  • Building lists is really verbose and will likely feature a lot of repetition / hard-to-read code.
    • You can bring in libraries like NBuilder to make this easier and more readable.
    • You can’t use the best parts of NBuilder if you are not using public property setters so you can enforce domain invariants.
  • Your approach to generating data will be largely inconsistent across test classes – some will have private methods, some will do it inline, some might delegate to factories or helper classes etc. – this makes the code hard to understand and maintain.
  • It’s not immediately clear which of the parameters you are passing into the constructor are there to meet the requirements of the call and which are there because the test dictates it – this means the intent of your test is somewhat obscured

Object Mother

A good approach to start to address the problem is to implement the Object Mother pattern. This allows you to quickly and tersely create pre-canned objects and give them a descriptive name. Now instead of having complex chains of object instantiations you have one line of code (e.g. ObjectMother.CustomerWith3FilledOrders), which is a lot more descriptive and your tests become simpler as a result. This also helps ensure that your approach for data generation is consistent, and thus more maintainable.

If you just use Object Mother though, you will likely observe the following problems:

  • While your constructor calls are likely to be in one file now, there is still potentially a lot of calls so it’s still tricky to make constructor changes.
  • As soon as you have a small tweak needed for the data returned there is a tendency to simply create a new Object Mother property.
  • Because of this, the Object Mother class can quickly get unwieldy and a nightmare to maintain and understand – it becomes a god object of sorts.

Test Data Builder

An approach that seems to have stemmed from the Object Mother pattern is the application of the builder pattern to result in the Test Data Builder pattern. This involves creating a builder class responsible for creating a particular type of object via a fluent interface that keeps track of the desired state of the object being built before being asked to actually build the object.

This provides a number of advantages:

  • Your constructor calls will be in your test project once only making them easy to change.
  • You have a readable, discoverable, fluent interface to generate your objects making your tests easy to read/write/maintain.
  • You are consistent in how you generate your test data.
  • It works with objects that you don’t have public property setters for since there is an explicit build action, which can invoke the constructor with the parameters you have set.
  • It’s flexible enough to give you the ability to express and perform actions to your object after it’s constructed – e.g. specify that an order is paid (which might be a Pay() method rather than a constructor parameter; you wouldn’t expect to be able to create an order in the paid state!).
  • Because of this your builder objects provide a blueprint / documentation for how to interact with your domain objects.
  • The test data builder can contain sensible defaults for your object instantiation and thus your test only needs to specify the values that need to be arranged thus making the intent of your test very clear
  • We have added a method to our builders (.AsProxy()) that allows the object returned to be an NSubstitute substitute (a proxy / mock object if you aren’t familiar with that library) rather than a real object (with the public properties set to automatically return the values specified in the builder). See below for a code snippet.
    • This means that when we need substitutes to check whether certain methods are called or to ensure that certain method calls return predetermined values we can generate those substitutes consistently with how we generate the real objects.
    • This is very powerful and improves understandability and maintainability of the tests.
    • In general we try and avoid using substitutes because it means that it’s possible to get objects that violate domain invariants, however, on occasion it’s very useful to properly unit test a domain action when it interacts with other domain objects

Here is a (somewhat contrived) example of the .AsProxy() method described above.

public void Given10YearMembership_WhenCalculatingDiscount_ThenApply15PercentLongMembershipDiscount() {
    var member = MemberBuilder.AsProxy().Build();
    member.GetYearsOfMembership(Arg.Any()).Returns(10);

    var discount = _discountCalculator.CalculateDiscountFor(member, new DateTimeProvider());

    Assert.That(discount, Is.EqualTo(0.15));
}

Combining NBuilder and the Test Data Builders

Another cool thing we have done is to combine our test data builders with NBuilder to allow for terse, expressive generation of lists of objects while still supporting objects that don’t have public property setters. We do this by generating a list of builders with NBuilder and then iterating that list to build each builder and get the actual object. Here is an example:

var members = Builder.CreateListOfSize(4)
    .TheFirst(1).With(b => b.WithFirstName("Rob"))
    .TheNext(2).With(b => b.WithFirstName("Poya"))
    .TheNext(1).With(b => b.WithFirstName("Matt"))
    .Build()
    .Select(b => b.Build());

We have made the above code even terser, by adding some extension methods to allow for this:

var members = MemberBuilder.CreateList(4)
    .TheFirst(1).With(b => b.WithFirstName("Rob"))
    .TheNext(2).With(b => b.WithFirstName("Poya"))
    .TheNext(1).With(b => b.WithFirstName("Matt"))
    .BuildList();

Adding back Object Mother

One of the really nice things about the Object Mother pattern is that you reduce a lot of repetition on your tests by re-using pre-canned objects. It also means the tests are a lot terser since you just specify the name of the pre-canned object that you want and assuming that name describes the pre-canned object well then your test is very readable.

What we have done is combined the maintainability and flexibility that is afforded by the Test Data Builder pattern with the terseness afforded by the Object Mother by using Object Mothers that return Test Data Builders. This overcomes all of the disadvantages noted above with the Object Mother pattern.

In order to make it easy to find objects we also use a static partial class for the Object Mother – this is one of the few really nice uses I’ve seen for partial classes. Basically, we have an ObjectMother folder / namespace in our test project that contains a file for every entity we are generating that includes a static nested class within the root ObjectMother class. This ensures that all test data is gotten by first typing “ObjectMother.” – this makes it really consistent and easily accessible, while not having an unmaintainable mess of a god object.

For instance we might have (simple example):

// Helpers\ObjectMother\Customers.cs
using MyProject.Tests.Helpers.Builders;

namespace MyProject.Tests.Helpers.ObjectMother
{
    public static partial class ObjectMother
    {
        public static class Customers
        {
            public static CustomerBuilder Robert
            {
                get { return new CustomerBuilder().WithFirstName("Robert"); }
            }
            public static CustomerBuilder Matt
            {
                get { return new CustomerBuilder().WithFirstName("Matt"); }
            }
        }
    }
}

If our test requires any small tweaks to the predefined object then you don’t need to necessarily add another property to your object mother – you can use the methods on the builder, e.g. ObjectMother.Customers.Robert.WithLastName("Moore").Build();

We generally stick to using properties rather than methods in the object mothers since the builders mean that it’s not necessary to pass any parameters to get your pre-canned object out, but occasionally we do have some that have methods when there is something meaningful to configure that makes sense in the object mother e.g. ObjectMother.Members.MemberWithXProducts(int numProducts).

Making the Test Data Builders terse

One argument against this approach, particularly when you first start out your test project (or indeed if you decide to refactor it to use this technique after the fact) is that you are writing a lot of code to get it all up and running. We decided to avoid that by using a number of techniques:

  • We set any reasonable defaults in our builder constructor so new CustomerBuilder().Build() will give a reasonable object (unless for that particular type of object there are any properties that make sense to always have to specify, in which case we don’t add a default for that property).
  • We have created a base class that allows us to set/get the property values into a dictionary using a lambda expression that identifies the property whose value is being set/retrieved – this reduces the code in the builder by eliminating the need for most (sometimes there is still a need to keep state in the builder where you are storing something not expressed by one of the properties) of the private variables in the builder.
  • We only add fluent methods for the properties we are actually using in our tests that point in time – this means we don’t have dead methods lying around in the builders and initially they are very terse.
  • We have a base class that defines a lot of the common infrastructure behind defining a builder (including the ability to return a proxy object and the ability to create a list of builders using NBuilder – I’ve open sourced the code as NTestDataBuilder).

This generally means that we can be up and running with an object mother and builder for a new entity within a minute and it’s well worth doing it from the start with all our objects to keep consistency in the codebase and ensure all tests are maintainable, terse and readable from the start.

Here is an example of what I mean from the NTestDataBuilder library I have released:

class CustomerBuilder : TestDataBuilder<Customer, CustomerBuilder>
{
    public CustomerBuilder()
    {
        WithFirstName("Rob");
        WithLastName("Moore");
        WhoJoinedIn(2013);
    }

    public CustomerBuilder WithFirstName(string firstName)
    {
        Set(x => x.FirstName, firstName);
        return this;
    }

    public CustomerBuilder WithLastName(string lastName)
    {
        Set(x => x.LastName, lastName);
        return this;
    }

    public CustomerBuilder WhoJoinedIn(int yearJoined)
    {
        Set(x => x.YearJoined, yearJoined);
        return this;
    }

    protected override Customer BuildObject()
    {
        return new Customer(
            Get(x => x.FirstName),
            Get(x => x.LastName),
            Get(x => x.YearJoined)
        );
    }
}

AzureWebFarm 0.9.2 Released

I’m happy to announce that I’ve just released AzureWebFarm 0.9.2 to Nuget.

This release involves months of work by myself and Matt Davies to really tighten up the farm, perform a lot of stress testing on it (including some reasonably heavy production loads) and take the (larger than we expected – I’ll do a separate blog post on this in the next few days) step to upgrade to Windows Server 2012 / .NET 4.5 support. We will be deploying this version to production farms over the next few weeks and if there are no issues then we will be releasing v1.0 in the near future.

I’m pleased to announce that with Windows Server 2012 and the Azure SDK 1.8 (which we’ve discovered comes with some quite massive and seemingly undocumented deployment speed improvements that we are reliably getting deployment times (including package upload) of around 9 minutes for a new web farm! We think this is incredible that you can get an enterprise-grade, clustered, load-balanced, IIS8 / Windows Server 2012 powered web farm with background execution capabilities that you can scale up and down in less than 10 minutes!!!

What’s new?

The changes we’ve introduced in this version are (in no particular order):

  • If a web.config file is included with a background worker application then it will no longer cause an exception in the web farm and in fact will not be overwritten
  • Upgraded to Azure SDK 1.8 along with the deployment speed improvements this entails
  • Decreased the number of files that are needed in the web farm web project significantly (now it’s just web.config, app.config, Probe.aspx, Probe.aspx.cs and WebRole.cs)
  • Added missing HTTP certificate config in the example cloud project config files
  • Set a bunch of internally used classes to `internal` from `public` to reduce the possibility of any confusion
  • Refactored core code to make it easier to unit test and maintain
  • Improved the test coverage of the codebase
  • Changes to config settings while the farm is deployed will now update the farm without requiring the roles to be manually restarted (the roles won’t automatically restart either – they will always use the latest version of the config settings)
  • Added handling to OnStop to ensure all ASP.NET requests are served before a role is restarted as per http://blogs.msdn.com/b/windowsazure/archive/2013/01/14/the-right-way-to-handle-azure-onstop-events.aspx
  • Added configurable logging via Castle.Core so you can adjust the verbosity of the trace logs and intercept the logs if you would like to redirect it to different instrumentation
  • Removed dependencies on Azure Storage within uncaught code called from OnRun() – this means that the web farm should not go down if there is an Azure Storage outage
  • Added configuration setting to allow for syncing to be disabled without needing to redeploy the farm
  • Added functionality to ensure all web deploy connections get funnelled to a single role instance at a time (with robust failover if that role instance fails). This resolves an issue when using MsDeploy v3+ on the server that we discovered and will be documented in a later blog post.
  • Changed the example config files to use Windows Server 2012
  • Opened up a readme.txt file when you install the NuGet package to outline any breaking changes
  • Improved documentation on github

Breaking Changes

If you are upgrading from a previous version of Azure Web Farm then make sure you look at the breaking changes file to see upgrade instructions as there are a number of breaking changes in this release.

Future Direction

What’s in store for Azure Web Farm in the future? This is a rough idea of the sorts of things we are looking into (we don’t have a timeline on this – if you want to help out to make it happen faster though please contact us):

  • Out of the box auto-scaling support using Wasabi
  • Better installation experience – using nuget install scripts to take away some of the tedious manual configuration when creating a new farm
  • Improving the syncing speed – it currently takes 30-90s to sync a new deployment across the farm and we are confident we can get that down significantly

TestStack.Seleno 0.4 released

Lately I’ve been spending a fair bit of spare time working hard on getting the TestStack.Seleno project ready for a (rather massive!) 0.4 release. It’s been a lot of fun and I’m quite proud of the impact the core TestStack team and other contributors have made on the library. We feel that it is “production ready” now and will be moving towards a 1.0 release in the somewhat near future.

I won’t bother going into a huge amount of detail on the release because Michael Whelan has done that already, but I’ll list down the major changes here as a tl;dr:

  • Added a bunch of global configuration options:
    • Ability to specify a Castle.Core logger factory to intercept our internal logging
    • Ability to more easily specify a non-Firefox web browser
    • Ability to specify a deployed web application out-of-the-box
    • Ability to more explicitly specify your MVC routes
    • Ability to override the minimum (implicit) wait timeout inside of Selenium
  • Ability to explicitly specify the initial page for a test and initialise the first page object in one line of code
  • Continuous Integration support (now runs in TeamCity)
  • A new HTML Control model that provides a nice API on top of Selenium Web Driver to interact with HTML controls (including easy extensibility for your own controls)
  • A clearer public API
  • Improved test coverage and extensive refactoring of the core library code

You can get the latest version of Seleno on NuGet, or check out our GitHub repository for the latest source code and the getting started documentation. Let us know what you think, or if there are any features that you would like to see. Feel free to add an issue or pull request – the more community interaction we get the better we can make Seleno!

Resolving request-scoped objects into a singleton with Autofac

This week I had an issue raised on my Github site for examples of unobtrusive validation with ASP.NET MVC. The person that raised the issue was having a problem where they wanted their fluent validation modules to be singleton, but they wanted to inject a factory that can be invoked to return a request-scoped object (in this case some sort of database store). Inevitably they came across the “No scope with a Tag matching ‘AutofacWebRequest’ is visible from the scope in which the instance was requested” error.

I’ve blogged previously about a technique for using DependencyResolver.Current and being able to unit test it for similar situations. It’s not a great solution, but it does work and at least it can be unit tested.

Low and behold though, thanks to the power of the Internet, the person that raised the issue asked a question on StackOverflow and got a really elegant solution for how to inject factories in a singleton that will correctly resolve request-scoped objects. I’m pretty excited about it so I thought I’d give it more exposure by doing this blog post.

This is the technique in all it’s glory (I’ve renamed the method name slightly to make it more readable):

public Func<T> HttpRequestScopedFactoryFor<T>()
{
    return () => DependencyResolver.Current.GetService<T>();
}

...

builder.RegisterType<SomeRequestScopedComponent>().As<ISomeRequestScopedComponent>().InstancePerHttpRequest();
builder.RegisterInstance(HttpRequestScopedFactoryFor<ISomeRequestScopedComponent>()); // this is the magic bit

This will then allow you to do something like this:

builder.RegisterType<SomeSingletonType>().As<ISomeSingletonType>().SingleInstance();

...

public class SomeSingletonType
{
    private readonly Func<ISomeRequestScopedComponent> _someRequestScopedComponentFactory;

    public SomeSingletonType(Func<ISomeRequestScopedComponent> someRequestScopedComponentFactory())
    {
        _someRequestScopedComponentFactory = someRequestScopedComponentFactory;
    }

    public void SomeMethod() {
        var requestScopedComponent = _requestScopedComponentFactory();
        ...
    }
}

Nice and even easier to unit test than using DependencyResolver.Current directly!

Big thanks to @thardy and @felix.

Announcing NHibernate.SqlAzure version 1.0!

I’m proud to be able to announce the release of version 1.0 of NHibernate.SqlAzure!

This library takes care of retrying when the transient errors that SQL Azure throws at you occur while using the NHibernate ORM. It’s been in Beta for the last few months and has been successfully used on a number of production websites.

Changes from 0.9 to 1.0

  • Bug fix when using Schema validation (thanks to @hmvs)
  • There is now a transient error detection strategy and associated NHibernate driver (SqlAzureClientDriverWithTimeoutRetries; say that 10 times fast!!) that retries for timeout exceptions (see the Github page for details and also thanks to @hmvs for a contribution towards this)
  • Some instances where exceptions where wrapped in NHibernate exceptions (batching, transactions) are now picked up as transient exceptions when before they were ignored
  • You can now easily log connection and command exceptions separately (see the CommandRetry and ConnectionRetry virtual methods on the driver class you use)
  • The documentation is a bit more comprehensive now
  • I finished writing all the automated tests I wanted to
  • Been road-tested on a number of sites over the last few months in production

This project is a collaborative effort along with my partner in code crime - Matt Davies – all code was either pair programmed together or reviewed by the other party.

Go and grab it from NuGet today and let me know how you go! Installation / usage instructions are on the Github page.

Running AspNetCompiler after creating web deploy package using VisualStudio 2012 with round-tripping to 2010

I’ve previously blogged (as a side-note of an unrelated problem I was having) the approach that I use to overcome the problem that the AspNetCompiler has when you have the extraneous web.config files in the obj folder after creating a web deploy package.

The usual way you will come across this problem is running MvcBuildViews in a subsequent build after creating the package. The solution that I previously posted included a few MSBuild targets that can be called prior to running MvcBuildViews to clean up the web deploy files.

If you have tried using these targets after upgrading your project to Visual Studio 2012 then you will have noticed that some of the targets no longer work because they have been renamed. The following code is what I now use and it is compatible with the Visual Studio 2010 round-tripping support.

  <Target Name="CleanWebDeploy" BeforeTargets="MvcBuildViews" Condition="'$(MvcBuildViews)'=='true'">
    <Message Text="Running Clean Web Deploy Target" />
    <CallTarget Targets="CleanWebsitesPackage" />
    <CallTarget Targets="CleanWebsitesPackageTempDir" Condition="'$(VisualStudioVersion)'=='10.0'" />
    <CallTarget Targets="CleanWebsitesTransformParametersFiles" Condition="'$(VisualStudioVersion)'=='10.0'" />
    <CallTarget Targets="CleanWebsitesWPPAllFilesInSingleFolder" Condition="'$(VisualStudioVersion)'!='10.0'" />
    <CallTarget Targets="CleanWebPublishPipelineIntermediateOutput" Condition="'$(VisualStudioVersion)'!='10.0'" />
  </Target>