martedì 27 luglio 2010

Entity Framework e il ProviderManifestToken

Quando si usa Entity Framework (sicuramente la versione 4, la prima immagino ma non ho mai provato) il modello si “lega” alla versione del database che si è indicato in fase iniziale. Tale legame viene scritto nel modello, precisamente nel ssdl, nella proprietà ProviderManifestToken e tale proprietà non è editabile dal designer. Ovviamente da tale proprietà dipende il tipo di codice SQL generato per le varie interrogazioni.
Questo può portare a problemi/fastidi se nell’ambiente di sviluppo si usa una versione di SQL Server differente da quella che si ha in ambiente di test/produzione. Se ad esempio si sviluppa su SQL Server 2008 ma sull’ambiente di produzione del cliente si ha SQL Server 2005 il nostro progetto rischia di non funzionare, soprattutto se usiamo dei campi data: la versione per SQL 2008 sfrutta il tipo datetime2 che in SQL 2005 non esiste.
La soluzione che ho adottato e che funziona correttamente in un sistema già rilasciato presso un cliente prevede i seguenti passi:

  1. Impostare il modello affinché non “embeddi” i file, tra cui l’ssdl, nella dll ma li copi nella cartella di output – in altre parole nelle proprietà del modello impostare Metadata Artifact Processing a “Copy to Output Directory” invece di “Embed in Output Assembly”
  2. Creare una semplice console application che prenda il file ssdl e vada a sostituire il valore del ProviderManifestToken (in fondo riporto un semplice codice d’esempio), e “linkarla” nel progetto che contiene il modello
  3. Impostare il post-buil event del progetto contenente il nostro modello affinché chiami la console application appena creata e successivamente copi i file del modello (csdl, msl ed ssdl) nel “bin” del nostro startup project (istruzione xcopy)
  4. Impostare il file di configurazione (nel mio caso il web.config) affinché la stringa di connessione punti correttamente ai file copiati con la post-build operation

Il semplice codice della console application che ho preparato è il seguente:

   1: static void Main(string[] args)
   2: {
   3:     string modelName = args[0];
   4:     string filePath = string.Format("./{0}.ssdl", modelName);
   5:  
   6:     var edmx = new XmlDocument();
   7:     edmx.Load(filePath);
   8:     var nsm = new XmlNamespaceManager(edmx.NameTable);
   9:     nsm.AddNamespace("a", "http://schemas.microsoft.com/ado/2009/02/edm/ssdl");
  10:     var x = edmx.SelectSingleNode("/a:Schema", nsm);
  11:     x.Attributes["ProviderManifestToken"].Value = "2005";
  12:     edmx.Save(filePath);
  13: }

In questo caso vuole il nome del modello in input così da dedurre il nome del file ssdl, e imposta di default il ProviderManifestToken a 2005. Ovviamente la modifica per prendere in input anche il valore da impostare al ProviderManifestToken è banale.

Alcuni link utili:

P.S. L’errore dato dall’applicativo dal quale è emerso questo comportamento legato al ProviderManifestToken è stato “SQL Server in use does not support datatype datetime2”.

Nessun commento:

Posta un commento