Castle.Windsor creating invalid version of SqlConnection with Dapper

We have a strange problem when using Castle.Windsor to instantiate an SqlConnection using a typed factory:

Registration is as follows:

container.Register(Component.For<IDbConnectionFactory>().AsFactory().LifestyleTransient()); container.Register(Component.For<IDbConnection>().ImplementedBy<SqlConnection>() .LifestyleTransient() .DependsOn(Dependency.OnValue<string> (ConfigurationManager.ConnectionStrings["DbConnectionString"].ConnectionString))); 

And IDbConnectionFactory :

 public interface IDbConnectionFactory { IDbConnection Create(); void Release(); } 

Now, when I try to access a new connection using this code:

 using (var connection = _connectionFactory.Create()) { } 

I get an exception:

 An unhandled exception of type 'Castle.MicroKernel.ComponentActivator.ComponentActivatorException' occurred in Castle.Windsor.dll Additional information: Error setting property SqlConnection.AccessToken in component System.Data.SqlClient.SqlConnection. See inner exception for more information. If you don't want Windsor to set this property you can do it by either decorating it with DoNotWireAttribute or via registration API. Alternatively consider making the setter non-public. 

The problem with this exception is that the SqlConnection type in System.Data for .NET 4.5.1 does not contain the AccessToken property, whereas in .NET 4.6. In other words, if I try to manually do

 var connection = new SqlConnection("connectionstring"); connection.AccessToken = ""; 

I get a build error if the project is configured for .NET 4.5.1, but a runtime error when installing AccessToken if it is configured for .NET 4.6.

Any idea why Castle.Windsor is trying to create a v4.6 SqlConnection instead of .NET 4.5.1?

Bypass / Hack

I can get around this problem by telling Castle to ignore the property, but it seems like a hack. To do this, I need to add it to PropertiesIgnore in the registration:

 container.Register(Component.For<IDbConnection>().ImplementedBy<SqlConnection>() .PropertiesIgnore(info => info.Name.Equals("AccessToken")) .LifestyleTransient() .DependsOn(Dependency.OnValue<string> (ConfigurationManager.ConnectionStrings["DbConnectionString"].ConnectionString))); 
+4
source share
1 answer

All versions of .NET starting with version 4.5 contain updates as you can see here .

This means that after installing .NET 4.6, you will always get the version of SqlConnection.NET 4.6 no matter how you create it.

When you create an application in Visual Studio, you create against a specific version of the .NET framework, usually located in the folder under: C: \ Program Files (x86) \ Reference Assemblies \ Microsoft \ Framework.NETFramework

This means that when creating msbuild, you can verify that you are not using what is not available in the version of the frame that you are targeting.

However, when launching your 64-bit application, it will use the assemblies usually located in C: \ Windows \ Microsoft.NET \ Framework64 \ v4.0.30319

This is the same folder for all versions from .NET 4.0 to .NET 4.6, which means the update means.

Therefore, when you run your application in your development environment on which .NET 4.6 is installed, you will always get the version of .NET 4.6 (at least if you do not do something special to download other versions of assemblies).

Castle Windsor will try to set properties using a public setter , and it will use reflection to find properties, which means it will find .NET. 4.6 on a .NET 4.6 machine, even if you create against 4.5.1.

The reason it fails when it tries to set the AccessToken is most likely because your connection string is incompatible with setting the AccessToken.

If you check the source code of the AccessToken installer, you will see that it will throw an exception if you try to set it for an incompatible connection string, even if you are only trying to set the AccessToken to an empty string.

Since you do not need to inject any dependencies into the SqlConnection object, you can simply create it using the new operator, and then you will avoid the problem caused by Windsors trying to inject connection properties. Using this registry should work:

 container.Register(Component.For<IDbConnection>().ImplementedBy<SqlConnection>() .LifestyleTransient() .UsingFactoryMethod(() => new SqlConnection (ConfigurationManager.ConnectionStrings["DbConnectionString"].ConnectionString))); 
+3
source

All Articles