2017-02-10 3 views
0

런타임시 데이터베이스 드라이버 어셈블리를로드하고 서버에 대한 연결을 수행 할 수 있어야합니다. .net core : 런타임시 어셈블리 및 해당 관리되지 않는 종속성로드

내 nuget 패키지에서 SQLite는 드라이버을로드 유형로드 할 콘솔 응용 프로그램의 예를 들면 : SqliteConnection합니다. 여기 내 의사 코드 :

System.DllNotFoundException : sqlite3를 'DLL로드 할 수 없습니다'를 그것이 관리되지 않는 종속성을 찾는 실패 cnn.Open() 점까지 작동

string path = Path.Combine(NugetPackagesDir, @"microsoft.data.sqlite\1.1.0\lib\netstandard1.3\Microsoft.Data.Sqlite.dll"); 
var myAssembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(path); 
var myType = myAssembly.GetType("Microsoft.Data.Sqlite.SqliteConnection"); 
IDbConnection cnn = (IDbConnection)Activator.CreateInstance(myType); 
cnn.ConnectionString = "Data Source=:memory:"; 
cnn.Open(); 

: '

나는 SQL Server 및 기본 의존성과 같은 문제가있어 6,

System.DllNotFoundException : 나는 그것이 작동하는 드라이버 패키지에 DLL을 복사,하지만 난 생각이 편리하지 찾을 경우 sni.dll '

'DLL로드 할 수 없습니다 '를.


UPDATE

모르겠어요 선행 DbConnection의 종류 I 인스턴스화 할 필요가 없으며 I가 오전 OS.

내 라이브러리가 Microsoft.Build.Utilities.Task을 구현하고 프로젝트 빌드 후 MsBuild.exe에 의해 시작된다는 컨텍스트가 있습니다. 그래서 DbConnection (및 구성 파일 또는 다른 곳의 드라이버 어셈블리 이름)을 원하는 응용 프로그램의 $ (TargetPath)이 있습니다.

.NET 세계에서 모든 어셈블리 (관리 대상이든 아니든)는 $ (TargetPath) 또는 GAC의 디버그/릴리스 폴더에 있습니다. 하지만 .net 코어에는 deps.json 파일 만 있습니다.

제 생각에는 DependencyContext 클래스를 사용하여 deps.json 파일을 읽으십시오. 사용중인 데이터베이스 드라이버를 찾고 어셈블리와 모든 종속성 (os에 따라 다름)을 복사하여 임시 폴더에 복사합니다. 여기서 임시로 DbConnection 클래스를 인스턴스화 할 수 있습니다.


업데이트 2

내 목표는 내가 개발하는 nuget 패키지를 사용하는 응용 프로그램의 SQL 마이그레이션 스크립트를 실행, 빌드 후, 수있을 것입니다. 그래서 내 코드는 대상 응용 프로그램이 아닌 MSBuild 작업 내에서 실행됩니다.

빌드가 완료되면 MsBuild 태스크가 대상 프로젝트 app.config 파일 (for.등 몇 가지 변수를 선언해야 NET) : 프로젝트

  • 연결 문자열
  • 마이그레이션 스크립트 폴더 (들)에 사용

    • 데이터베이스 드라이버를 ... 그 데이터와

    그런 다음 DbConnection을 만들고 지정된 폴더에서 찾은 스크립트를 실행합니다.

  • +0

    몇 가지를 명확히 할 수 있습니까? 이 MSBuild 작업은 어떻게 사용됩니까? 사용할 DbConnection의 유형을 어떻게 결정합니까? 연결 문자열의 출처는 무엇입니까? 올바른 구현은 MSBuild가 컴파일중인 앱에서 코드를 실행하려고하는지 또는 빌드 단계로 MSBuild 내에서 무언가를 실행하려고하는지에 따라 달라집니다. – natemcmaster

    +0

    답을 업데이트했습니다. 당신이하려는 일은 어렵습니다. 나는 더 간단한 접근법을 제안했지만, 전체 솔루션은 스택 오버 플로우 응답에서 설명하기에는 너무 길다. – natemcmaster

    답변

    0

    가장 쉬운 방법은 런타임에서 자동으로 어셈블리 로딩을 처리하도록하는 것입니다. Assembly.Load를 호출하지 마십시오. 대신 Microsoft.Data.Sqlite 및 System.Data.SqlClient NuGet 패키지에 대한 참조를 프로젝트에 추가하십시오.

    <PackageReference Include="Microsoft.Data.Sqlite" Version="1.1.0" /> 
    <PackageReference Include="System.Data.SqlClient" Version="4.3.0" /> 
    

    당신이 project.json를 사용하는 경우, 그것은 DbConnection의 다른 구현 사이를 전환 클래스를 추가, 그리고

    { 
        "dependencies": { 
         "Microsoft.Data.Sqlite": "1.1.0", 
         "System.Data.SqlClient": "4.3.0" 
        } 
    } 
    

    입니다 : 같은 csproj 및 VS 2017, 이것은 보인다.

    public class MyConnectionFactory 
    { 
        public DbConnection Create(string serverType, string connectionString) 
        { 
         if (serverType == "sqlite") return new SqliteConnection(connectionString); 
         else if (serverType == "sqlserver") return new SqlConnection(connectionString); 
    
         throw new ArgumentException($"{serverType} not supported"); 
        } 
    } 
    

    어셈블리 로딩 논리를 직접 구현하려고하면 원치 않는 상처를 입을 수 있습니다. 대신 NuGet 패키지를 사용하십시오.

    어떤 종류의 DbConnection을 원하는지 미리 알지 못하는 경우 문제가 될 수 있습니다. 이것이 시나리오라면 NuGet 캐시의 모든 관리되지 않는 라이브러리와 관리되는 라이브러리를 응용 프로그램 기본 디렉토리 (Program.Main이있는 어셈블리의 위치)로 복사해야합니다. 이것은 권장 접근법이 아니므로 .NET 코어가 여러 운영 체제 (Linux, macOS) 및 플랫폼 (x86, x64, ARM)에서 작동하도록하려면 작동하지 않습니다.

    의 MSBuild MSBuild에서 호스트 및 조립 부하 제어와 같이 매우 어려운 일이 될 것입니다 내부 아마도 관리되지 않는 코드 실행 편집. MSBuild에서 DbConnection을 호출하는 콘솔 응용 프로그램으로 새로운 .NET 코어 프로세스를 시작하는 것이 더 간단한 해결책 일 것입니다.

    +0

    감사합니다. 내 질문을 지정했습니다. 나는 좋은 가정을하고 있는가? –

    관련 문제