web-dev-qa-db-fra.com

Erreur lors de l'exécution de la procédure stockée CLR sur Azure SQL Managed Instance: «L'assembly dans le magasin hôte a une signature différente de l'assembly dans GAC»

J'ai une procédure stockée CLR qui s'exécute correctement lorsqu'elle est déployée sur des instances SQL Server locales à partir de SQL Server 2012 - 2017. Je peux réussir le déploiement sur une instance gérée Azure SQL mais lorsque j'exécute la procédure, j'obtiens l'erreur suivante:

Impossible de charger le fichier ou l'assembly "System.Net.Http, version = 4.0.0.0, Culture = neutre, PublicKeyToken = b03f5f7f11d50a3a" ou l'une de ses dépendances. L'assemblage dans le magasin hôte a une signature différente de l'assemblage dans GAC. (Exception de HRESULT: 0x80131050).

J'ai essayé de jouer avec les références du projet mais en vain - la seule version du System.Net.Http.dll qui peut être déployée sur l'instance gérée est une erreur lors de l'exécution.

5
JamesP

L'une des exigences/nuances de l'utilisation de SQLCLR est que tout assembly chargé à la fois dans le GAC et dans SQL Server doit être la version exactement la même chose (c'est-à-dire jusqu'au niveau du correctif, pas seulement Major.Minor . *). Ainsi, vos instances locales peuvent toutes utiliser 4.7.2 (ou autre), mais si l'instance gérée utilise 4.7, 4.7.1, 4.8 ou toute autre chose, vous obtiendrez cette erreur. Vous obtiendriez même cette erreur si l'une de vos instances locales se trouvait sur un serveur exécutant une version différente de .NET Framework que celle que vous avez récupérée System.Net.Http.DLL de. Bien sûr, si toutes ces différentes instances que vous avez mentionnées s'exécutent sur le même serveur physique, alors il n'y a qu'un seul système d'exploitation impliqué de toute façon, alors bien sûr, elles fonctionnent toutes correctement ;-).

Vous devrez découvrir quelle version spécifique est utilisée sur l'instance gérée et l'utiliser dans votre script d'installation Azure. Vous ne devriez pas avoir besoin d'utiliser la même version localement car la référence à une version similaire qui a les mêmes signatures devrait fonctionner.

Maintenant, comment trouver la version exacte du Framework sur l'instance gérée? La requête suivante semble être le meilleur moyen d'obtenir ces informations:

SELECT olm.[name], olm.[file_version]
FROM   sys.dm_os_loaded_modules olm
WHERE  olm.[name] LIKE N'%mscoreei.dll%';

O.P. a répondu que la requête ci-dessus renvoyait une version de 4.7: 2623.0 sur le
Instance gérée et une version de 4.7: 3190.0 sur le système local (sur site).

Ceci est la source de l'erreur " L'assembly dans le magasin hôte a une signature différente de l'assembly dans GAC"

Donc, pour que cela fonctionne, vous devez trouver cette version spécifique de cette DLL et la conditionner pour la charger dans l'instance gérée.

P.S. Ce problème est l'un des inconvénients de l'utilisation de bibliothèques .NET Framework non prises en charge. Ils vont être dans le GAC (généralement, non?) Et si une mise à jour Windows (localement, ou quoi qu'ils fassent au système hôte des instances gérées) met à jour la version, alors votre projet SQLCLR cesse de fonctionner. Et, si le nouveau Framework non pris en charge DLL est converti en un assembly en mode mixte (code managé et non managé), vous ne pourrez pas charger la nouvelle version dans SQL Server et aurez besoin pour recoder votre projet afin de ne pas utiliser cet assembly Framework non pris en charge.

P.P.S. Pourquoi utilisez-vous System.Net.Http pour? S'il s'agit de services Web, vous devez simplement utiliser les classes System.Net.HttpWebRequest et HttpWebResponse. Vous devrez faire un peu de codage supplémentaire pour construire et analyser le XML de la demande Web, mais ces classes existent dans une bibliothèque entièrement prise en charge.

O.P. replied back with: "Correct, web services stuff."

Plus tard, O.P. a répondu: "J'ai réussi à déployer et à exécuter un SQLCLR de base
procédure sur une instance gérée utilisant uniquement HttpWebRequest et HttpWebResponse,
Je pense qu'il vaudrait mieux aller dans cette direction jusqu'à ce que Microsoft étende la liste des bibliothèques prises en charge nativement .. "

P.P.P.S. Vous voudrez peut-être jeter un œil à SQL # (une bibliothèque SQLCLR que j'ai écrite), car il existe une procédure stockée qui gère cela, basée sur HttpWebRequest. Il gère la plupart (sinon la totalité) des en-têtes HTTP gérés en interne, permet d'envoyer des en-têtes personnalisés (y compris l'ID utilisateur/mot de passe, si nécessaire), l'envoi de données POST/GET, et même d'autres éléments que la plupart juste une pensée, mais pour une divulgation complète, alors qu'il existe une version gratuite, INET_GetWebPages est uniquement dans la version complète (payante) .

6
Solomon Rutzky

De différences T-SQL de l'instance gérée Azure SQL Database par rapport à SQL Server :

Une instance gérée ne peut pas accéder aux partages de fichiers et aux dossiers Windows, les contraintes suivantes s'appliquent donc:

Et ensuite:

Les modules CLR et les serveurs liés ne peuvent parfois pas référencer une adresse IP locale

Les modules CLR placés dans une instance gérée et les serveurs liés ou les requêtes distribuées qui référencent une instance actuelle ne peuvent parfois pas résoudre l'IP d'une instance locale. Cette erreur est un problème transitoire.

Solution: utilisez des connexions de contexte dans un module CLR si possible.

L'une de ces restrictions pourrait être ce qui vous bloque; sinon, il serait utile d'ajouter plus d'informations à votre question sur ce que fait votre procédure CLR, et comment vous avez confirmé que chacune de ces restrictions ne s'applique pas. Une recherche de +CLR +"Managed Instance" donne exactement deux résultats, donc si rien ici ne s'applique, je suggère d'engager le support Microsoft.

2
Aaron Bertrand