Castle.Windsor가 Dapper로 잘못된 버전의 SqlConnection을 인스턴스화합니다.

.net-4.5 .net-4.6 c# castle-windsor dapper

문제

Castle.Windsor를 사용하면 입력 된 팩토리를 사용하여 SqlConnection을 인스턴스화 할 때 이상한 문제가 발생합니다.

등록은 다음과 같습니다.

container.Register(Component.For<IDbConnectionFactory>().AsFactory().LifestyleTransient());

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

그리고 IDbConnectionFactory :

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

이제이 코드를 사용하여 새 연결에 액세스하려고하면 다음과 같습니다.

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

}

나는 예외를 얻는다 :

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.

이 예외 문제는 .NET 4.5.1 용 System.Data의 SqlConnection 형식이 AccessToken 속성을 포함하지 않는 반면 .NET 4.5에서는 System.Data의 SqlConnection 형식이 해당 속성을 포함하지 않는다는 것입니다. 즉, 내가 수동으로 시도하면

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

프로젝트가 .NET 4.5.1로 구성되었지만 .NET 4.6 용으로 구성된 경우 런타임 오류로 AccessToken을 설정하면 빌드 오류가 발생합니다.

Castle.Windsor가 .NET 4.5.1 대신 v4.6 SqlConnection을 만드는 이유는 무엇입니까?

해결 방법 / 해킹

캐슬에게 속성을 무시하라고 말하면서 문제를 해결할 수 있습니다. 그러나 이것은 해킹처럼 보입니다. 이렇게하려면 등록시 PropertiesIgnore 에 추가해야합니다.

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

수락 된 답변

4.5 버전부터 모든 .NET 버전 을 볼 수 있습니다 .

즉, .NET 4.6을 설치하면 인스턴스화 방법에 관계없이 항상 .NET 4.6 버전의 SqlConnection을 얻을 수 있습니다.

Visual Studio에서 응용 프로그램을 빌드 할 때 일반적으로 C : \ Program Files (x86) \ Reference Assemblies \ Microsoft \ Framework.NETFramework 아래의 폴더에있는 .NET Framework의 특정 버전에 대해 빌드합니다.

즉, msbuild를 빌드 할 때 대상 프레임 워크 버전에서 사용할 수없는 것을 사용하고 있지 않은지 확인할 수 있습니다.

그러나 64 비트 응용 프로그램을 실행할 때 일반적으로 C : \ Windows \ Microsoft.NET \ Framework64 \ v4.0.30319에있는 어셈블리를 사용합니다

이 폴더는 .NET 4.0에서 .NET 4.6까지의 모든 버전에서 동일한 폴더입니다.

따라서 .NET 4.6이 설치된 개발 환경에서 응용 프로그램을 실행하면 항상 다른 버전의 어셈블리를로드하는 특별한 작업을 수행하지 않는 한 .NET 4.6 버전이 제공됩니다.

Castle Windsor는 public setter로 속성설정 하려고 시도하며 4.5.1에 ​​대해 빌드하는 경우에도 .NET 4.6 시스템에서 .NET 4.6 속성을 찾을 수 있다는 것을 나타내는 속성을 찾기 위해 리플렉션을 사용합니다.

AccessToken을 설정하려고 할 때 실패하는 이유는 연결 문자열이 AccessToken을 설정하는 것과 호환되지 않기 때문일 가능성이 큽니다.

AccessToken setter의 소스 코드 를 확인하면 AccessToken을 빈 문자열로 설정하려고해도 호환되지 않는 연결 문자열로 설정하려고하면 예외가 발생합니다.

SqlConnection 개체에 종속성을 삽입 할 필요가 없으므로 new 연산자를 사용하여 간단히 만들 수 있습니다. 그런 다음 Windsors가 연결 속성을 주입하려고 시도 할 때 발생하는 문제를 피할 수 있습니다. 이 등록을 사용하면 효과가 있습니다.

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


아래 라이선스: CC-BY-SA with attribution
와 제휴하지 않음 Stack Overflow
아래 라이선스: CC-BY-SA with attribution
와 제휴하지 않음 Stack Overflow