Che cos’è il ciclo di vita di integrazione CLR di SQL Server?

Come sono gestiti gli oggetti CLR (.NET) in SQL Server?

Il punto di ingresso a qualsiasi codice CLR da SQL Server è un metodo statico. Generalmente creerai solo oggetti che esistono nell’ambito di questo metodo. Tuttavia, è ansible memorizzare i riferimenti agli oggetti nei membri statici, consentendo loro di sfuggire all’ambito di chiamata del metodo. Se SQL Server conserva questi oggetti in memoria tra più chiamate memorizzate di procedure / funzioni, potrebbero essere utili per la memorizzazione nella cache delle applicazioni, anche se sarebbero anche più pericolose.

In che modo viene trattato da SQL Server? Permette anche membri statici (non metodici)? Se è così, quanto a lungo li conserva in memoria? Garbage Collection raccoglie tutto dopo ogni chiamata CLR? Come gestisce la concorrenza?

In “Pro SQL Server 2005 Assemblies” di Robin Dewson e Julian Skinner, si afferma che “Gli assembly caricati in un database, come altri oggetti di database, sono di proprietà di un utente del database. Tutti gli assembly posseduti dallo stesso utente nello stesso database verranno eseguiti all’interno dello stesso AppDomain. Gli assembly di proprietà di un utente diverso verranno eseguiti in un AppDomain separato. ”

Ciò che questo mi dice è che se stai lavorando con un singolo database e tutti gli assembly che carichi con l’istruzione CREATE ASSEMBLY hanno lo stesso proprietario, allora tutti gli assembly verranno eseguiti nello stesso dominio dell’app. Tuttavia, essere nello stesso AppDomain non significa usare lo stesso code-base, quindi anche la stessa DLL può essere caricata negli stessi domini dell’applicazione più volte, e i suoi tipi non corrispondono, anche se hanno lo stesso nome. Quando i tipi con lo stesso nome provengono da basi di codice diverse, le loro variabili statiche saranno anche istanze diverse.

L’unico modo in cui posso vedere di utilizzare le variabili statiche in modo sicuro nell’ambiente CLR di SQL Server con più assembly è in realtà solo utilizzare un singolo assembly. È ansible utilizzare l’utility ILMerge con l’opzione “UnionMerge” per raggruppare tutti gli assembly in uno e unire classi con lo stesso nome. Questo dovrebbe garantire che per un dato database, nel tuo unico assemblaggio, le tue variabili statiche funzioneranno proprio come farebbero in un’applicazione standalone. Penso che sia sicuro supporre che il dominio dell’applicazione non sia scaricato e ricaricato ad ogni richiesta, ma non si può dipendere dal fatto che non viene mai scaricato, poiché ciò avverrà ogni volta che si verifica un errore non gestito (almeno se è in esecuzione in modalità non sicura ).

SQL Server consente ai membri statici di sola lettura se l’assembly viene distribuito con il livello di authorization Non sicuro.

In pratica gli oggetti vengono mantenuti in memoria fino a quando il servizio SQL non viene arrestato / riavviato.

Per quanto riguarda la concorrenza, il tuo object e i tuoi metodi dovrebbero essere thread-safe come ovunque.

Per esempio:

public static class MyCLRClass { private static readonly ReaderWriterLock rwlock = new ReaderWriterLock(); private static readonly ArrayList list = new ArrayList(); private static void AddToList(object obj) { rwlock.AcquireWriterLock(1000); try { list.Add(obj); } finally { rwlock.ReleaseLock(); } } [SqlProcedure(Name="MyCLRProc")] public static void MyCLRProc() { rwlock.AcquireReaderLock(1000); try { SqlContext.Pipe.Send(string.Format("items in list: {0}", list.Count)); } finally { rwlock.ReleaseLock(); } } } 

Io uso queste cose in SQL CLR e funziona.

Non concepibilmente; molto puoi creare membri statici. MA, devono essere contrassegnati come readonly per gli assembly che hanno un PERMISSION_SET di SAFE o EXTERNAL_ACCESS . Solo un assembly contrassegnato come UNSAFE può avere membri statici scrivibili. E questa restrizione è dovuta alla natura stessa dei membri statici: sono condivisi tra thread e sessioni.

Un assembly viene caricato la prima volta che si accede a un metodo al suo interno. È condiviso per tutte le sessioni da utilizzare, motivo per cui solo i metodi statici sono accessibili. L’idea è di scrivere funzioni, non un’applicazione, quindi non è molto utile mantenere lo stato. E può facilmente (anche se certamente non sempre) portare a comportamenti imprevedibili se varie sessioni si sovrascrivono a vicenda. Quindi la concorrenza non viene gestita affatto, a meno che non si scriva quella parte da soli.

È probabile che, una volta caricata, la class (e il dominio App in cui risiede) rimarrà in memoria fino al riavvio del servizio SQL Server o al cambiamento del valore PERMISSION_SET . Ma questo non è garantito. In base a questa pagina, Utilizzo della memoria in SQL CLR :

quando c’è una pressione di memoria sul server, SQL CLR proverà a rilasciare memoria eseguendo esplicitamente la garbage collection e, se necessario, scaricando appdomain.

Quindi sei corretto su entrambi i fronti per quanto riguarda i membri statici:

  • possono essere usati per il caching (molto cool)
  • possono essere più pericolosi:
    • possono causare comportamenti imprevisti
    • possono bind la memoria in quanto non esiste alcun meccanismo intrinseco o evento naturale per ripulirli perché la class rimane triggers.

Inoltre, la quantità di memoria disponibile per le routine CLR varia notevolmente a seconda che SQL Server sia 32 o 64 bit e se si stia utilizzando SQL Server 2005/2008/2008 R2 o utilizzando SQL Server 2012/2014. Per maggiori informazioni su quanto memoria con cui SQLCLR deve giocare, controlla SQL Server 2012 Memoria e utilizzo memoria in SQL CLR (come il primo link, pubblicato sopra l’offerta).

Ecco alcune informazioni che ho trovato.

Problemi con lo stato condiviso e delegati anonimi in SQLCLR

Non solo lo stato condiviso non è consentito in un assembly non UNSAFE, ma i delegati anonimi (sfortunatamente) triggersno questa restrizione “stato condiviso”.

Dalla specifica C # 3.0 (5.1.1)

Una variabile statica entra in esistenza prima dell’esecuzione del costruttore statico (§10.12) per il suo tipo di contenitore e cessa di esistere quando il dominio dell’applicazione associato cessa di esistere.

Sicuramente non spegnerà l’intero dominio dell’applicazione dopo ogni chiamata poiché sarebbe un po ‘inefficiente. Quindi sì, questi oggetti statici rimangono lì finché il database non viene fermato o riavviato.