So aktualisieren Sie eine CLR-Assembly, ohne die Assembly von SQL Server zu löschen

18

Wie kann ich eine CLR-Funktions- (oder Prozedur-) Assembly-DLL aktualisieren, ohne die Assembly in SQL Server (2008 R2) löschen und neu erstellen zu müssen?

Wie es jetzt steht, wenn ich eine Assembly aktualisiere (z. B. um eine neue Funktion hinzuzufügen), wird SQL Server die aktualisierte DLL nicht berücksichtigen, bis ich die Assembly lösche:

DROP ASSEMBLY CLRFunctions

Msg 6590, Level 16, State 1, Line 1
DROP ASSEMBLY failed because 'CLRFunctions' is referenced by object 'NormalizeString'.

Aber bevor ich die Assembly löschen kann, muss ich zuerst alle Funktionen löschen , die darauf verweisen:

DROP FUNCTION NormalizeString
DROP FUNCTION RemoveDiacritics
DROP FUNCTION RemoveCombiningDiacritics
DROP FUNCTION CombineLigatures
....
DROP FUNCTION PseudolocalizeArabic

Und dann kann ich die Baugruppe fallen lassen:

DROP ASSEMBLY CLRFunctions

Jetzt muss ich die Baugruppe " erstellen ":

CREATE ASSEMBLY CLRFunctions FROM 'c:\foos\CLRFunctions.dll';

Und jetzt muss ich die Deklaration aller UDFs suchen, die registriert wurden , bevor ich sie löschte.

Ich würde lieber eine Assembly aktualisieren und SQL Server damit beginnen lassen, sie zu verwenden.


Update : Ich habe zufällig versucht DBCC FREEPROCCACHE, eine "Neukompilierung" zu erzwingen, aber SQL Server verwendet immer noch den alten Code.

Update : Ich habe die Assembly-DLL gelöscht CLRFunctions.dllund SQL Server ist weiterhin in der Lage, den Code auszuführen (ohne Code, der unmöglich sein sollte).

Ian Boyd
quelle

Antworten:

16

Ich glaube, du suchst alter assembly. Von BOL:

Wenn die FROM-Klausel angegeben ist, aktualisiert ALTER ASSEMBLY die Assembly in Bezug auf die neuesten Kopien der bereitgestellten Module. Da in der SQL Server-Instanz möglicherweise CLR-Funktionen, gespeicherte Prozeduren, Trigger, Datentypen und benutzerdefinierte Aggregatfunktionen vorhanden sind, die bereits für die Assembly definiert sind, werden sie mit der Anweisung ALTER ASSEMBLY erneut an die neueste Implementierung der Assembly gebunden. Um diese erneute Bindung durchzuführen, müssen die Methoden, die CLR-Funktionen, gespeicherten Prozeduren und Triggern zugeordnet sind, in der geänderten Assembly noch mit denselben Signaturen vorhanden sein. Die Klassen, die benutzerdefinierte CLR-Typen und benutzerdefinierte Aggregatfunktionen implementieren, müssen weiterhin die Anforderungen erfüllen, um ein benutzerdefinierter Typ oder ein benutzerdefiniertes Aggregat zu sein.

Eines der Beispiele auf derselben Seite scheint den Trick zu machen:

ALTER ASSEMBLY ComplexNumber 
FROM 'C:\Program Files\Microsoft SQL Server\90\Tools\Samples\1033\Engine\Programmability\CLR\UserDefinedDataType\CS\ComplexNumber\obj\Debug\ComplexNumber.dll' 
Ben Thul
quelle
1
Ist dies möglich, wenn sich die aktualisierte Assembly nicht auf dem SQL Server-Hostcomputer, sondern auf dem SSMS-Clientcomputer befindet? Ich habe nicht genügend Berechtigungen auf dem Server, um direkt auf sein Dateisystem zuzugreifen, aber ich habe ausreichende Berechtigungen, um CLR-Assemblys hinzuzufügen und zu entfernen.
Zarepheth
Nein, meistens nein. Sie können einen UNC-Pfad (dh \\ Server \ Pfad \ zu \ Datei) angeben. Solange das Dienstkonto, unter dem die SQL-Engine ausgeführt wird, über Leseberechtigungen für die Datei verfügt, sollte dies funktionieren. Die andere Option besteht darin, den Binärwert für die Assembly anzugeben. Wenn Sie es bereits auf einem anderen Server bereitgestellt haben, erhalten Sie den Blob-Wert, wenn Sie die Änderung von dort per Skript ausführen.
Ben Thul
Ja das ist, was ich dachte. :( Möglicherweise ermöglicht eine neuere Version von SSMS das Aktualisieren von Assemblys von einem Remote-Computer. In der Zwischenzeit schätze ich, dass ich Assemblys über die SSMS-GUI ablege und erstelle - und für alle abhängigen Funktionen
DROP-
Ich würde den Atem nicht anhalten. Warum können Sie keine der oben beschriebenen Methoden anwenden, wenn Sie nachlassen und neu erstellen müssen?
Ben Thul
1
"Das Hinzufügen und Ändern von Assemblys erfordert eine Dateisystemreferenz." - das ist nicht wahr. Beide CREATE ASSEMBLYund ALTER ASSEMBLYnehmen einen Blob, der die Assembly darstellt. Stellen Sie dies selbst unter Beweis, indem Sie zu jeder ab 2008 erstellten Datenbank gehen und unter Programmierbarkeit -> Assemblys die Erstellung der Microsoft.SqlServer.Types-Assembly per Skript ausführen. Das gigantische Varbinary ist die Versammlung . Da dies auf Ihre Situation zutrifft, stellen Sie Ihre Assembly auf Ihrer lokalen Instanz bereit, skripten Sie sie aus und machen Sie sie zu einem ALTER ASSEMBLYSkript.
Ben Thul
7

Um die Antwort von Ben Thul zu ergänzen, kann dies relativ einfach über die grafische Benutzeroberfläche von SQL Server Management Studio aus der Ferne erfolgen .

  1. Klicken Sie im Objekt-Explorer Ihrer Datenbank -> Programmierbarkeit mit der rechten Maustaste auf Baugruppen und wählen Sie 'Neue Baugruppe ...'.

  2. Navigieren Sie zu Ihrer aktualisierten DLL.

  3. Anstatt auf "OK" zu klicken (was fehlschlägt, da bereits eine Baugruppe mit demselben Namen vorhanden ist), klicken Sie oben im Fenster "Neue Baugruppe" auf "Skript".
     
    Sie werden zu einer SQL-Abfrage weitergeleitet, die eine Zeile 'CREATE ASSEMBLY' gefolgt von einem riesigen Blob enthält, bei dem es sich um die gerade ausgewählte DLL handelt.

  4. Ändern Sie 'CREATE' in 'ALTER' und führen Sie dann aus!

Das Skript hat auch eine AUTHORIZATION-Zeile für mich erstellt, die ich vor der Ausführung entfernen musste. Ihre Laufleistung kann variieren.

Ich hoffe das hilft jemand anderem ohne Dateisystemzugriff auf ihre Server.

Hoffentlich wird Microsoft dies eines Tages zu einem erstklassigen Vorgang in SSMS machen, aber dies ist eine ziemlich einfache Umgehung, bis sie dies tun.

F. Shinn
quelle
1

Ich habe einen Hinweis auf die Antwort auf Stackoverflow gefunden :

ALTER ASSEMBLY CLRFunctions FROM 'c:\foos\CLRFunctions.dll';
Ian Boyd
quelle
1
Sie meinten ALTER ASSEMBLY... ( UPDATEist in DML, ALTERist in DDL.)
Miroxlav