Uno dei "problemi" di fondo di SQL Express è che offre una capacità limitata in termini di connessioni contemporanee. Questo fatto è in taluni casi penalizzante, forse direi che sono più i casi penalizzanti che quelli non, ma del resto il prodotto è qualcosa di fascia minore che serve per supplire alla mancanza di SQL Server e di tute le caratteristiche di tale prodotto.
Comunque, cerchiamo di analizzare meglio il discorso. Intanto diciamo che SQL Express è nato quasi esclusivamente ad uso e consumo degli sviluppatori e dell'IDE di Visual Studio. Che poi dopo si sia pensato di renderlo adatto anche al deployment di piccoli siti web o di piccole applicazioni che necessitano di un database che non sia l'ormai obsoleto Access, è tutt'altra storia.
La struttura di SQL (Server o Express) prevede che ogni database sia composto da una coppia di file. Un file .mdf e un file .log. Questi due file lavorano a braccetto e non si possono mischiare. Se si fa l'aggiornamento di versione di un database file, bisogna farla anche del suo log file, se si fa il downgrade anche, se si decide di portare quel database da una parte all'altra, sempre e comunque quei due file devono viaggiare assieme.
In tutte le operazioni, questi due file saranno sempre validati reciprocamente l'uno contro l'altro per verificare l'esatta appartenenza dei due file alla coppia. Questo è quello che avviene anche quando si fa l'attach del db presso un'istanza di un database.
Fare l'attach di un database file, significa - per l'utente normale (o supponiamo anche di essere amministratori di un Db server) – compiere 4 passaggi almeno: in sequenza utilizzare un SQL Command per fare l'attach del db, creare un utente specifico per consentire al proprietario del db di fare la login sul DB Server, autorizzare quel login ad utilizzare il suo db, assegnare i permessi sugli oggetti del db e le autorizzazioni necessarie a far funzionare il database e/o l'applicazione che vi si appoggia sopra.
In condizioni di sviluppo, ci si è resi conto che gli ultimi 4 passaggi erano ripetitivi e dispendiosi in termini di tempo. Di li, le User Instances e il comando AttachDbFileName.
Non entro nel merito di stringhe di connessioni e altro perché non è lo scopo di questo post.
Modificando il provider di dati SQL e aggiungendo la possibilità di utilizzare paroline come "AttachDBFileName" e "Integrated Security" (User Instance) si è messo in condizioni il provider e il motore SQL di poter creare al volo istanze di SQL Server, e far girare il database specificato con gli stessi permessi dell'utente che ha generato l'istanza di SQL. Tante parole per dire in fondo che con questo comando il povero sviluppatore, se non ha un DB Server o non ha cognizioni di Database Management, può comunque evitare di dover imparare un sacco di cose (che non fanno mai male) ed essere subito produttivi sin dal primo debug.
Questo però vuol dire anche un'altra cosa. Tralasciando tutti gli aspetti di security e robine varie, per far funzionare questo giochino dell'istanza creata al volo, i file del database in questa particolare condizione devono necessariamente essere loccati dall'utente che vi accede e questo lock deve essere di tipo esclusivo, perché le modifiche al database veicolano prima in memoria e poi vengono scritte persistentemente sul database file. Se fosse consentito un accesso simultaneo (più utenti, più applicazioni) a quei file, potrebbe succedere lo sfacelo.
Questo lock per quanto sia utile a prevenire problemi, comporta anche dei rallentamenti.
Si supponga questo mio caso reale. Ero al lavoro su di un sito web che si appoggia ad SQL Express. Stavo sviluppando delle pagine, modifico, premo F5, cambio qualche cosa, aggiorno la pagina direttamente nel browser, e ad un certo punto mi accorgo che devo cambiare un tipo di dati o semplicemente aggiungere dei dati a mano dentro a delle tabelle per fare prima.
Ok, apro il database con il Server Explorer di Visual Studio, faccio le modifiche e premo ancora aggiorna da dentro al browser. Inzio a vedere dei rallentamenti pazzeschi sulla pagina che non smette più di caricare, fintanto che non mi becco l'errore "Cannot find table 0" che meglio analizzato si traduce in "l'utente NETWORK SERVICE" non ha i permessi necessari. Ma come? Fino a due minuti prima stavo lavorando e tutto funzionava … ora che cosa è successo?
Semplice. Dopo aver perso diverse ore a cercare di capire quali potessero essere le cause – adesso sintetizzo – mi sono finalmente reso conto che la semplice connessione con il Server Explorer dell'IDE di Visual Studio, faceva il detach del db da quell'istanza di SQL in memoria, distruggeva l'istanza, creava un nuovo utente, nuova istanza, nuovo collegamento, ma a differenza della pagina web che nasce e muore con il caricamento della pagina stessa, l'IDE di Visual Studio rendeva quasi "persistente" l'istanza e non consentiva più collegamenti se prima non si clicca sul database e si fa "Close connection".
Stesso discorso, ma leggermente più articolato, succede se si tenta di aprire il database con SQL Management Studio. Anzi direi che li non basta fare close connection. Li bisogna fare il detach del database, specificando di droppare tutte le connessioni. E non sempre si è fortunati, perché in taluni casi, la User Instance rimane comunque aperta con l'errore accennato prima.
Cosa fare? C'è chi mi ha consigliato di non usare SQL Express, ma questa non è una scelta di diretta competenza dello sviluppatore, per lo meno non lo è sempre.
L'alternativa è usare gli strumenti giusti, ovvero le SQL Server Express Utility. Stando a quando scritto all'interno del file di help sembra che queste servano a risolvere i problemi, quindi nello specifico a fare il detach del DB e riportare la situazione alla normalità, ed evitare quindi di perdere tempo con errori che non c'entrano un fico secco con quello che dichiarano. Nella realtà, non so ancora dirvi e mi riservo un ulteriore post, dopo che mi sarà nuovamente capitato il problema (o me lo farò ricapitare) e avrò provato l'utility in questione.
Spero di aver semplificato al massimo il discorso e al contempo di non aver scritto castronerie. Comunque per maggiori approfondimenti si può sempre leggere l'articolo in inglese direttamente dal sito della Microsoft.