Search code examples
c#.netentity-framework-6devartdll-reference

Can I specify the absolute location for <entityFramework>.<providers>.<provider> in App.config


  <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>

I am developing an add-in library for an application (ESRI ArcMap). At the same time, I would like to use EF6 as DB Accessing. My problem is that the application crashed every time when it executes DbProviderFactories.GetFactory("Devart.Data.Oracle") and an error is prompted as Devart.Data.Oracle Failed to find or load the registered .Net Framework Data Provider.

I sure that all required libraries are placed in the same folder with the main add-in DLL. However, the main application exe is not in the same place with the add-in DLL. Seems that the application load its add-in DLL by searching through the add-in folder separately.

My observation is that DbProviderFactories.GetFactory searches for the providers DLL only within the folder of which the exe located at. Therefore, it cannot find the provider DLL which is located in the add-in folder. May I know if there is any way to specify where should DbProviderFactories.GetFactory search for the provider DLL?

Thanks in advance.


Solution

  • The DbProviderFactories registration via code:

    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");
      }
    }
    

    Loading Devart.* assemblies from YourSubDirName:

     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;
        }