LINQ to SQL : modificare dinamicamente il mapping del database (schema)

ATTENZIONE! Il post ha più di 2 anni e le informazioni contenute potrebbero essere obsolete (ad esempio a causa di un aggiornamento di versione rispetto agli elementi descritti o links modificati da siti esterni).

Durante lo sviluppo di un’applicazione web si passa spesso tra diversi server: sviluppo, test, produzione. In ognuno il nome dello schema potrebbe cambiare oppure può capitare di non poter utilizzare lo schema dbo creato di default da Visual Studio (ad esempio su hosting Aruba). Per non dover modificare ogni volta l’intero file di mapping e risparmiare tempo è possibile caricare a runtime il file di mapping con lo schema corretto in base all’ambiente.

Ecco come:

STEP 1 Come prima cosa, dopo aver creato il database, si crea il file .dbml con il designer LINQ to SQL. Per convenienza chiamiamo il file local.dbml.

STEP 2 Ora tramite SqlMetal.exe è possibile generare un file di mapping. Solitamente si punta al database, ma per non perdere eventuali modifiche fatte al file local.dbml si usa il file stesso come punto iniziale. SqlMetal.exe si trova solitamente in C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin.

E’ possible utilizzarlo da lì oppure copiarlo in una qualsiasi cartella. Supponendo di averlo copiato in C: , aprire il prompt dei comandi e inserire il seguente comando (modificandolo in base alle esigenze):

SqlMetal /map:"server_schema.map" "C:\Users\UtenteUno\Documents\Visual Studio 2008\Projects\mioprogetto\mioprogetto\local.dbml" /code:"server_schema.vb"

I tre parametri passati sono rispettivamente:

  • il nome del file .map di output (servirà dopo)
  • il percorso per il file .dbml creato in precedenza tramite il designer
  • il codice di output in .vb

STEP 3 SqlMetal creerà quindi i files server_schema.vb e il file server_schema.map. Il file server_schema.vb può essere cancellato mentre il file .map deve essere aperto con un editor (può andar bene anche il notepad) per modificare i nomi delle tabelle (o meglio, degli schemi). Ad esempio:



<Table Name="dbo.photogallery" Member="photogallery">

diventerà, supponendo che lo schema di destinazione sia MSSQL8548:



<Table Name="MSSQL8548.photogallery"  Member="photogallery">

I files creati andranno salvati tutti in una cartella all’interno del progetto. In questo esempio la chiameremo sqlmap. STEP 4 Sempre per non modificare più files è preferibile salvare tutti i parametri necessari all’interno del file web.config. Il parametro ServerLocation indica il server attuale in uso. I nomi dei parametri connection string sono precedute dal nome del server per poter essere meglio identificate.


<appSettings>
 <!-- seleziona il server tra:
 local
 server
 ...(altri servers: dev,test,ecc)
 -->
 <add key="SeverLocation" value="local" />
</appSettings>

<connectionStrings>
 <!-- lista delle connection strings -->
 <add name="local_ConnectionString" connectionString="..."
 providerName="System.Data.SqlClient" />

 <add name="aruba_ConnectionString" connectionString="..."
 providerName="System.Data.SqlClient" />
</connectionStrings>

STEP5
A questo punto con poche righe di codice si gestisce il mapping dinamico del database. Il codice è in VB.NET, per C#ci sono da fare solo delle piccole modifiche a livello di sintassi. Mentre il codice originale era qualcosa simile a:

'inizializzazione del DataContext
Dim db As LocalDataContext = New LocalDataContext()
'esecuzione della query
qry = From gallery In db.photogallery _
      Order By gallery.photogallery_id Descending _
      Select gallery

ora diventerà:

'server in cui è l'applicazione viene eseguita
Dim serverLocation As String = ConfigurationManager.AppSettings.Get("SeverLocation")
'lettura della stringa di connessione
Dim cString = ConfigurationManager.ConnectionStrings(serverLocation + "_ConnectionString").ConnectionString()
'lettura del mapping creato con SqlMetal
Dim mapFile As String = HttpContext.Current.Server.MapPath("\") + "sqlmap\" + serverLocation + "_schema.map"
Dim linqMapping = System.Data.Linq.Mapping.XmlMappingSource.FromReader(System.Xml.XmlReader.Create(mapFile))
'inizializzazione del DataContext
Dim db As DatiSitoDataContext = New DatiSitoDataContext(cString, linqMapping)
'esecuzione della query
qry = From gallery In db.photogallery _
      Order By gallery.photogallery_id Descending _
      Select gallery

Naturalmente anche la funzione per ricavare il data context corretto si può inserire in una classe ad accesso globale.

 
 
Server dedicato

Condividi questo post


Commenti