2017-03-21 4 views
1

J'ai une application .net qui fait référence à l'assembly Microsoft.SqlServer.Smo. L'assembly n'est pas distribué avec l'application. Au lieu de cela, sql sdk est installé dans le système et la DLL est enregistrée dans le GAC afin que l'application puisse charger. Cela ne pose aucun problème, sauf que sur certaines machines cibles, j'ai la version 12 du SDK, alors que sur d'autres, j'ai la version 13 du SDK (qui est généralement installée avec SSMS). Je voudrais que l'application charge la dernière version de tout ce qui est disponible sur le système, donc v13 ou, si elle n'est pas disponible, v12. Est-il possible de réaliser cela en code ou via la configuration de l'application?.net charger la dernière version de l'assembly

+0

Est-ce votre machine de développement/construction machine configurée avec l'ensemble Microsoft.SqlServer.Smo dans le GAC comme les machines cibles? – sevzas

+0

oui ma machine dev a la v11, v12 et v13 dans le GAC – gigi

+1

On dirait que le chemin à parcourir est de définir la propriété SpecificVersion de la référence à Smo assembly sur false dans votre fichier .csproj. Voir si cette réponse aide http://stackoverflow.com/questions/1063459/net-reference-specificversion-true-or-false – sevzas

Répondre

0

La réponse courte à la question est de définir SpecificVersion sur false comme correctement suggéré par @sevzas.

Quoi qu'il en soit, si sur le système est installé SSMS 2016 mise à jour 13.0.16000.28, le 13.100.0.0 de la DLL sera enregistré dans le GAC et avec la modification ci-dessus, c'est la version qu'il sera chargé. Malheureusement, cette version n'est pas destinée à être utilisée par des développeurs tiers, mais uniquement par les produits Microsoft, donc essayer de la charger génèrera une exception (see here). Quelqu'un pourrait se demander à ce stade pourquoi ils l'enregistrent dans le GAC s'ils ne veulent pas que les gens l'utilisent.

Quoi qu'il en soit, j'ai trouvé un moyen de charger la v13.0 (ou précédente, ou future 14) avec le code ci-dessous en utilisant l'événement de résolution d'assembly.

static int Main(string[] args) 
    { 
     //we set an event handler at the begging of our program 
     AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve; 
     //your stuff 
    } 

    private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) 
    { 
     //if the dll is a sqlserver dll, we do our trick 
     if(args.Name.StartsWith("Microsoft.SqlServer")) 
      return LoadSqlAssembly(args.Name); 

     return null; 
    } 

    private static readonly int[] SqlVersions = new int[] {14, 13, 12, 11}; 

    private static bool _reEntry = false; 

    private static Assembly LoadSqlAssembly(string name) 
    { 
     if (_reEntry) 
      return null; 

     name = name.Split(',')[0]; 

     foreach (var version in SqlVersions) 
     { 
      try 
      { 
       _reEntry = true; 
       var ret = Assembly.Load($"{name}, Version={version}.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL"); 
       //Logger.InfoFormat("Loaded {0} version {1}", name, version); 
       return ret; 
      } 
      catch (Exception) 
      { 
       //ignore exception 
      } 
      finally 
      { 
       _reEntry = false; 
      } 
     } 

     return null; 
    } 

`` `