Domanda

Ho creato un modello di framework di entità su un database 2008. Tutto funziona bene con il database 2008. Quando provo ad aggiornare l'entità su un database 2005 ottengo questo errore.

The version of SQL Server in use does not support datatype 'datetime2

In particolare non ho usato nessuna funzionalità del 2008 quando ho creato il database. Non riesco a trovare alcun riferimento a datetime2 nel codice. E sì, la colonna è definita come "datetime" nel database.

È stato utile?

Soluzione

Un rapido google mi indica ciò che sembra soluzione .

Apri il tuo EDMX in un editor di file (o "apri con ..." in Visual Studio e seleziona Editor XML). Nella parte superiore troverai il modello di archiviazione e ha un attributo ProviderManifestToken. Questo dovrebbe avere il valore 2008. Cambialo in 2005, ricompila e tutto funziona.

NOTA: dovrai farlo ogni volta che aggiorni il modello dal database.

Altri suggerimenti

Visualizzazione rapida della linea:

<Schema Namespace="Foobar.Store" Alias="Self" Provider="System.Data.SqlClient" ProviderManifestToken="2005" >

Questo è molto frustrante e sono sorpreso che MS abbia deciso di non farlo in modo da poter scegliere come target una determinata versione di SQL. Per essere sicuro che stiamo prendendo di mira il 2005, ho scritto una semplice app per console e la ho chiamata in un passaggio PreBuild.

Il passaggio di pre-build è simile al seguente:

$(SolutionDir)Artifacts\SetEdmxVer\SetEdmxSqlVersion $(ProjectDir)MyModel.edmx 2005

Il codice è qui:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;

namespace SetEdmxSqlVersion
{
    class Program
    {
        static void Main(string[] args)
        {
            if (2 != args.Length)
            {
                Console.WriteLine("usage: SetEdmxSqlVersion <edmxFile> <sqlVer>");
                return;
            }
            string edmxFilename = args[0];
            string ver = args[1];
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.Load(edmxFilename);

            XmlNamespaceManager mgr = new XmlNamespaceManager(xmlDoc.NameTable);
            mgr.AddNamespace("edmx", "http://schemas.microsoft.com/ado/2008/10/edmx");
            mgr.AddNamespace("ssdl", "http://schemas.microsoft.com/ado/2009/02/edm/ssdl");
            XmlNode node = xmlDoc.DocumentElement.SelectSingleNode("/edmx:Edmx/edmx:Runtime/edmx:StorageModels/ssdl:Schema", mgr);
            if (node == null)
            {
                Console.WriteLine("Could not find Schema node");
            }
            else
            {
                Console.WriteLine("Setting EDMX version to {0} in file {1}", ver, edmxFilename);
                node.Attributes["ProviderManifestToken"].Value = ver;
                xmlDoc.Save(edmxFilename);
            }
        }
    }
}

Utilizzando la comoda app console di @ Vance sopra, ho usato quanto segue come evento BeforeBuild

<Target Name="BeforeBuild">
    <!--Check out BD.edmx, Another.edmx, all configs-->
    <Exec Command="$(SolutionDir)\Library\tf checkout /lock:none $(ProjectDir)Generation\DB.edmx" />
    <Exec Command="$(SolutionDir)\Library\tf checkout /lock:none $(ProjectDir)Generation\Another.edmx" />
    <!--Set to 2008 for Dev-->
    <Exec Condition=" '$(Configuration)' == 'DEV1' " Command="$(SolutionDir)Library\SetEdmxSqlVersion $(ProjectDir)Generation\DB.edmx 2008" />
    <Exec Condition=" '$(Configuration)' == 'DEV1' " Command="$(SolutionDir)Library\SetEdmxSqlVersion $(ProjectDir)Generation\Another.edmx 2008" />
    <Exec Condition=" '$(Configuration)' == 'DEV2' " Command="$(SolutionDir)Library\SetEdmxSqlVersion $(ProjectDir)Generation\DB.edmx 2008" />
    <Exec Condition=" '$(Configuration)' == 'DEV2' " Command="$(SolutionDir)Library\SetEdmxSqlVersion $(ProjectDir)Generation\Another.edmx 2008" />
    <!--Set to 2005 for Deployments-->
    <Exec Condition=" '$(Configuration)' == 'TEST' " Command="$(SolutionDir)Library\SetEdmxSqlVersion $(ProjectDir)Generation\DB.edmx 2005" />
    <Exec Condition=" '$(Configuration)' == 'TEST' " Command="$(SolutionDir)Library\SetEdmxSqlVersion $(ProjectDir)Generation\Another.edmx 2005" />
    <Exec Condition=" '$(Configuration)' == 'PRODUCTION' " Command="$(SolutionDir)Library\SetEdmxSqlVersion $(ProjectDir)Generation\DB.edmx 2005" />
    <Exec Condition=" '$(Configuration)' == 'PRODUCTION' " Command="$(SolutionDir)Library\SetEdmxSqlVersion $(ProjectDir)Generation\Another.edmx 2005" />
  </Target>

Questo è molto utile, in quanto evita fastidiose ridistribuzioni. Grazie per aver condiviso Vance.

Ho aggiunto TF.exe alla cartella della soluzione Library e questo mi aiuta, dato che ora posso controllare i file edmx prima di provare a modificarli, come parte della build. Inoltre ho aggiunto questo con le condizioni, in modo che sia impostato su 2005 per le distribuzioni sul server e di nuovo sul 2008 per le configurazioni sln della macchina Dev. Inoltre, è necessario aggiungere i file SetEdmxSqlVersion.exe (e .pdb) effettivi alla cartella Libreria (o ovunque si desideri conservare questi bit).

Grazie mille @Vance. Davvero pulito, enorme risparmio di tempo e mantiene le mie build totalmente automatizzate e senza dolore :)

A beneficio delle persone che riscontrano lo stesso problema ma utilizzano prima il codice , controlla la mia risposta qui su come modificare il ProviderManifestToken in Code First. Implica la creazione manuale di un DbModelBuilder e il passaggio di un'istanza DbProviderInfo (con il token appropriato) quando si chiama il metodo Build del builder di modelli.

Si è verificato un problema simile con il 2012 rispetto al 2008. Può essere risolto con un evento BeforeBuild utilizzando XmlPeek e XmlPoke:

   <Target Name="BeforeBuild">
      <XmlPeek XmlInputPath="$(ProjectDir)MyModel.edmx"
               Namespaces="&lt;Namespace Prefix='edmx' Uri='http://schemas.microsoft.com/ado/2009/11/edmx'/&gt;&lt;Namespace Prefix='ssdl' Uri='http://schemas.microsoft.com/ado/2009/11/edm/ssdl'/&gt;"
               Query="/edmx:Edmx/edmx:Runtime/edmx:StorageModels/ssdl:Schema/@ProviderManifestToken">
         <Output TaskParameter="Result" ItemName="TargetedSQLVersion" />
      </XmlPeek>

      <XmlPoke Condition="@(TargetedSQLVersion) != 2008"
               XmlInputPath="$(ProjectDir)MyModel.edmx"
               Namespaces="&lt;Namespace Prefix='edmx' Uri='http://schemas.microsoft.com/ado/2009/11/edmx'/&gt;&lt;Namespace Prefix='ssdl' Uri='http://schemas.microsoft.com/ado/2009/11/edm/ssdl'/&gt;"
               Query="/edmx:Edmx/edmx:Runtime/edmx:StorageModels/ssdl:Schema/@ProviderManifestToken"
               Value="2008">
      </XmlPoke>
   </Target>

Se non ti piace la sostituzione automatica, puoi semplicemente sostituire l'attività XmlPoke con un'attività Errore.

La soluzione migliore per me è invece di modificare manualmente il file EDMX è aprire edmx in modalità progettazione e nel menu di scelta rapida "Aggiorna modello dal database ...". Devi puntare alla giusta versione SQL, ovviamente, qualunque cosa sia per te.

Abbiamo riscontrato questo errore su SQL2005 v.3, dove non lo avevamo su SQL2005 v.4.

L'aggiunta di SQL2005 alla stringa di connessione ha risolto il nostro problema specifico.

Non abbiamo ancora identificato il perché e non volevamo modificare il codice per fornire il token come risolto in precedenza (problema manifestato durante la distribuzione).

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top