web-dev-qa-db-fra.com

Utilisation de SQL Server 2008 et SQL Server 2005 et de l'heure

J'ai construit un modèle de structure d'entité par rapport à une base de données de 2008. Tout fonctionne bien contre la base de données 2008. Lorsque j'essaie de mettre à jour l'entité sur une base de données 2005, j'obtiens cette erreur. 

La version de SQL Server utilisée ne prend pas en charge le type de données 'datetime2

En particulier, je n’ai utilisé aucune fonctionnalité de 2008 lors de la construction de la base de données. Je ne trouve aucune référence à datetime2 dans le code. Et, oui, la colonne est définie comme "datetime" dans la base de données. 

118
Monroecheeseman

Un rapide Google me renvoie à ce qui ressemble à la solution .

Ouvrez votre EDMX dans un éditeur de fichier (ou «ouvrez avec…» dans Visual Studio et sélectionnez Éditeur XML). En haut, vous trouverez le modèle de stockage et son attribut ProviderManifestToken. Cela devrait avoir la valeur 2008. Changez-le en 2005, recompilez et tout fonctionne.

REMARQUE: vous devrez le faire chaque fois que vous mettrez à jour le modèle à partir de la base de données.

191
Richard Harrison

Aperçu rapide de la ligne:

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

C'est très frustrant et je suis surpris que MS ait décidé de ne pas le faire pour pouvoir cibler une version SQL donnée. Pour être sûr de cibler 2005, j'ai écrit une application console simple et je l'ai appelée dans une étape de pré-construction.

L'étape de pré-construction ressemble à ceci:

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

Le code est ici:

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);
            }
        }
    }
}
11
Vance Kessler

En utilisant l'application de console pratique de @ Vance ci-dessus, j'ai utilisé ce qui suit comme événement 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>

Ceci est super pratique, car évite un redéploiement ennuyeux. Merci d'avoir partagé Vance.  

J'ai ajouté TF.exe dans le dossier de la solution Library, ce qui m'aide à récupérer les fichiers edmx avant d'essayer de les modifier, dans le cadre de la construction. De plus, j'ai ajouté ceci avec des conditions, de sorte qu'il soit défini sur 2005 pour les déploiements sur le serveur et sur 2008 pour les configurations sln de la machine de développement. Vous devez également ajouter les fichiers réels SetEdmxSqlVersion.exe (et .pdb) au dossier Bibliothèque (ou à tout autre endroit où vous souhaitez conserver ces bits). 

Merci beaucoup @Vance. Vraiment ordonné, gain de temps massif et garde mes constructions totalement automatisées et sans douleur :) 

4
MemeDeveloper

Pour le bénéfice des personnes qui rencontrent le même problème mais qui utilisent Code First, consultez ma réponse ici sur la façon de changer la ProviderManifestToken dans Code First. Cela implique la création manuelle d'une DbModelBuilder et la transmission d'une instance DbProviderInfo (avec le jeton approprié) lors de l'appel de la méthode Build du constructeur du modèle.

2
sinelaw

Avait un problème similaire avec 2012 vs. 2008. Il peut être résolu avec un événement BeforeBuild utilisant XmlPeek et 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>

Si vous n'aimez pas le remplacement automatisé, vous pouvez simplement remplacer la tâche XmlPoke par une tâche d'erreur.

2
Edgar

La meilleure solution pour moi est au lieu d’éditer manuellement le fichier EDMX, c’est simplement ouvrir edmx en mode création et dans le menu contextuel "Mettre à jour le modèle à partir de la base de données ..." . vous.

1
Marek

Nous avons eu cette erreur sur SQL2005 v.3 alors que nous ne l'avions pas sur SQL2005 v.4.

L'ajout de SQL2005 à la chaîne de connexion a résolu notre problème spécifique.

Nous n'avons pas encore identifié pourquoi et ne souhaitons pas modifier le code pour fournir le jeton comme résolu ci-dessus (problème manifesté lors du déploiement).

0
Brian H