0
  <entityFramework>
    <providers>
      <provider invariantName="Devart.Data.Oracle" type="Devart.Data.Oracle.Entity.OracleEntityProviderServices, Devart.Data.Oracle.Entity.EF6, Version=9.14.1204.0, Culture=neutral, PublicKeyToken=09af7300eec23701" />
      <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
    </providers>
  </entityFramework>

我正在为应用程序(ESRI ArcMap)开发一个加载项库。同时,我想使用 EF6 作为 DB Accessing。我的问题是应用程序每次执行时都会崩溃DbProviderFactories.GetFactory("Devart.Data.Oracle")并提示错误为Devart.Data.Oracle Failed to find or load the registered .Net Framework Data Provider.

我确信所有必需的库都与主加载项 DLL 放在同一个文件夹中。但是,主应用程序 exe 与加载项 DLL 不在同一个位置。似乎应用程序通过单独搜索加载项文件夹来加载其加载项 DLL。

我的观察是,DbProviderFactories.GetFactory仅在 exe 所在的文件夹中搜索提供程序 DLL。因此,它找不到位于加载项文件夹中的提供程序 DLL。我可以知道是否有任何方法可以指定在哪里DbProviderFactories.GetFactory搜索提供程序 DLL?

提前致谢。

4

1 回答 1

1

通过代码注册 DbProviderFactories:

private static void InitDbProvFactEntry() {
  bool DevartProviderRegistered = false;
  var dataSet = System.Configuration.ConfigurationManager.GetSection("system.data") as System.Data.DataSet;
  foreach (System.Data.DataRow dr in dataSet.Tables[0].Rows) {
    if ((string)dr[2] == "Devart.Data.Oracle") {
      DevartProviderRegistered = true;
    }
  }
  if (!DevartProviderRegistered) {
    dataSet.Tables[0].Rows.Add("dotConnect for Oracle"
        , "Devart dotConnect for Oracle"
        , "Devart.Data.Oracle"
        ,
        "Devart.Data.Oracle.OracleProviderFactory, Devart.Data.Oracle, Version=" + Devart.Data.Oracle.ProductInfo.Version + ", Culture=neutral, PublicKeyToken=09af7300eec23701");
  }
}

从 YourSubDirName 加载 Devart.* 程序集:

 AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
...
    private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) {

      var assemblyName = new AssemblyName(args.Name);
      if (assemblyName.Name.StartsWith("Devart.")) {
        var assembly = Assembly.GetExecutingAssembly();
        string directory = System.IO.Path.GetDirectoryName(assembly.Location);
        string newPath = Path.Combine(directory, "YourSubDirName");
        var files = Directory.EnumerateFiles(newPath);
        string targetDllName = assemblyName.Name + ".dll";
        if (files.Any(name => name.EndsWith(targetDllName))) {
          string fullFilePath = Path.Combine(newPath, targetDllName);
          return Assembly.LoadFrom(fullFilePath);
        }
      }

      return null;
    }
于 2021-03-25T11:38:13.033 回答