117

Ich habe ein Entity-Framework-Modell für eine 2008-Datenbank erstellt. Alles funktioniert gut gegen die Datenbank 2008. Wenn ich versuche, die Entität in einer 2005-Datenbank zu aktualisieren, erhalte ich diesen Fehler.Mit SQL Server 2008 und SQL Server 2005 und Datum Uhrzeit

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

Ich habe speziell keine 2008-Features verwenden, wenn ich die Datenbank aufgebaut. Ich kann keinen Verweis auf Datetime2 im Code finden. Und, ja, die Spalte ist in der Datenbank als "datetime" definiert.

Antwort

192

Eine schnelle Google zeigt mir, was wie die solution aussieht.

Öffnen Sie Ihre EDMX in einem Dateieditor (oder "Öffnen mit ..." in Visual Studio und wählen Sie XML-Editor). Oben finden Sie das Speichermodell und es hat ein Attribut ProviderManifestToken. Dies sollte den Wert 2008 haben. Ändere das auf 2005, kompiliere neu und alles funktioniert.

HINWEIS: Sie müssen dies jedes Mal tun, wenn Sie das Modell aus der Datenbank aktualisieren.

+2

Ich habe dies versehentlich nach unten, öffnete das, aber jetzt kann nicht tun, was ich wirklich tun wollte, was es ist vote up! Vielen Dank, dass Sie das Problem gefunden haben. Wenn ich das richtig verstehe, ändert sich der Wert von 2005 auf 2008, weil das Modell aus der Datenbank aktualisiert wird, wobei die Datenbank eine SQL 2008 DB ist? In meiner Umgebung hat meine Entwicklungsmaschine SQL 2008, aber die Testumgebung hat 2005 (welche Produktion hat auch). Bis ich auf 2008 umgestiegen bin, habe ich recht, wenn ich annehme, dass dies weiterhin passieren wird? – jamiebarrow

+0

Ich setze das im Allgemeinen auf 2005, was die Produktionsdatenbank ist; Ich benutze 2008 für die Entwicklung. 2008 ist abwärtskompatibel also keine Probleme. Auch dies soll nach einem Update/Generieren wieder geändert werden. Ich bestätige dies immer, wenn ich nach bitterer Erfahrung den EDMX einchecke. –

+0

WOW, tolle Wiederholung, danke RECHARD –

12

Schnellansicht Linie:

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

bessere Lösung für mich, anstatt manuell bearbeiten EDMX-Datei ist nur offen edmx im Design-Modus und im Kontextmenü „Update Modell aus der Datenbank ...“. Sie müssen auf die richtige SQL-Version natürlich zeigen, was auch immer das für Sie ist.

+1

Ich denke, das OPs ist Problem - er entwickelt gegen eine lokale SQL 2008, aber dann zu SQL 2005 bereitgestellt. – StuartLC

+0

Dies funktioniert, es sei denn, Sie haben keinen Zugriff auf eine SQL 2005-Instanz. – Darcy

+1

Ein großer Nachteil ist, dass es ein manueller Schritt ist und somit vergessen wird. – Jowen

11

Dies ist sehr frustrierend und ich bin überrascht, MS entschied sich, es nicht zu machen, so dass Sie eine bestimmte SQL-Version targeten konnten. Um sicherzugehen, dass wir auf 2005 ausgerichtet sind, habe ich eine einfache Konsolen-App geschrieben und sie in einem PreBuild-Schritt aufgerufen.

Der vorkompilierte Schritt wie folgt aussieht:

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

Der Code ist hier:

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); 
      } 
     } 
    } 
} 
+0

Danke, eine einfache Lösung für nerviges Problem – Brian

+0

@Vance vielen Dank, perfekt. Ein bisschen langsam, da ich drei Edmx-Dateien habe, die ich ändern muss, kann also eine Lösungskonfiguration hinzufügen, die nach einer Bereitstellung zurückgesetzt wird, und sie aus dem normalen Build entfernen. Wird jetzt eine Antwort mit der Info für die Verwendung dieses handlichen Tools in einem BeforeBuild (oder AfterBuild) anstatt Pre-Build veröffentlichen. Sehr geschätzt. – MemeDeveloper

4

Mit @ Vance handliche Konsole App oben, habe ich die folgenden als Before Ereignis

<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> 

Das ist super praktisch, da lästiges Umsetzen vermieden wird. Danke, dass Sie Vance teilen.

Ich habe TF.exe zum Bibliotheks-Lösungsordner hinzugefügt und dies hilft, da ich jetzt die EDMX-Dateien auschecken kann, bevor ich versuche, sie als Teil des Builds zu bearbeiten. Auch ich habe dies mit Bedingungen hinzugefügt, so dass es für die Bereitstellungen auf dem Server und zurück zu 2005 für die Dev-Maschinen-SLN-Konfigurationen festgelegt wird. Außerdem müssen Sie die Datei SetEdmxSqlVersion.exe (und .pdb) zum Bibliotheksordner hinzufügen (oder wo auch immer Sie diese Bits behalten möchten).

Vielen Dank @Vance. wirklich ordentlich, massiven Schoner und hält meine Builds völlig automatisiert und schmerzfrei :)

2

Zum Wohle der Menschen, die das gleiche Problem auftritt, sind aber mit -Code Erste Besuche my answer here darüber, wie die ProviderManifestToken sich ändern in Code zuerst. Sie müssen DbModelBuilder manuell erstellen und eine DbProviderInfo Instanz (mit dem entsprechenden Token) übergeben, wenn Sie die Build Methode des Modell-Builders aufrufen.

+0

Ich denke Set 'Type System Version = SQL Server 2005' in Verbindungszeichenfolge funktioniert möglicherweise auch – code4j

1

haben ein ähnliches Problem mit 2012 vs. 2008. Es kann mit einem Ereignisse Before mit XmlPeek und XmlPoke gelöst werden:

<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> 

Wenn Sie automatischen Ersatz nicht mögen, können Sie einfach die XmlPoke Aufgabe mit einem Fehler ersetzen Aufgabe.

+0

Dies ist viel besser als die Verwendung einer externen ausführbaren Datei, ermöglicht MSBuild, all die Phantasie-intern zu behandeln. Dies kann alles leicht über 'CallTarget'-bedingte Pre-Build-Zielaufgaben in Abhängigkeit von Publish/Build-Konfigurationen verkettet werden. (ZB nur bei der Bereitstellung in einer SQL2005-Umgebung ändern) – admalledd

0

Wir hatten diesen Fehler auf SQL2005 v.3, wo wir es nicht auf SQL2005 v.4 haben.

SQL2005 zur Verbindungszeichenfolge Hinzufügen von festen unser spezifisches Problem.

Wir nicht identifiziert haben, warum noch, und wollte nicht den Code modifizieren, die Token zur Verfügung zu stellen, wie oben (bei der Bereitstellung manifestiert Ausgabe) gelöst.