Korzystanie z SQL Server 2008 i SQL Server 2005 oraz daty i godziny

118

Zbudowałem model struktury encji na podstawie bazy danych z 2008 roku. Wszystko działa dobrze w stosunku do bazy danych z 2008 roku. Kiedy próbuję zaktualizować jednostkę w bazie danych 2005, pojawia się ten błąd.

Używana wersja programu SQL Server nie obsługuje typu danych „datetime2

W szczególności nie korzystałem z żadnych funkcji 2008 podczas tworzenia bazy danych. Nie mogę znaleźć żadnego odniesienia do datetime2 w kodzie. I tak, kolumna jest w bazie danych zdefiniowana jako „data / godzina”.

Monroecheeseman
źródło

Odpowiedzi:

189

Szybkie wygooglowanie wskazuje mi, co wygląda na rozwiązanie .

Otwórz EDMX w edytorze plików (lub „otwórz za pomocą…” w programie Visual Studio i wybierz Edytor XML). U góry znajdziesz model magazynu i ma atrybut ProviderManifestToken. To powinno mieć wartość 2008. Zmień to na 2005, przekompiluj i wszystko działa.

UWAGA: Będziesz musiał to zrobić za każdym razem, gdy aktualizujesz model z bazy danych.

Richard Harrison
źródło
2
Głosowałem na to przez pomyłkę, cofnąłem to, ale teraz nie mogę zrobić tego, co naprawdę chciałem, czyli zagłosować za tym! Dziękuję za znalezienie problemu. Jeśli dobrze rozumiem, czy wartość zmienia się od 2005 do 2008 z powodu aktualizacji modelu z bazy danych, gdzie bazą danych jest SQL 2008 DB? W moim środowisku moja maszyna deweloperska ma SQL 2008, ale środowisko testowe ma 2005 (podobnie jak produkcja). Do czasu przejścia na rok 2008, czy mam rację zakładając, że to będzie się powtarzać?
jamiebarrow
Generalnie ustawiłem to na rok 2005, czyli produkcyjną bazę danych; Używam 2008 do programowania. 2008 jest kompatybilny wstecz, więc nie ma problemów. Również to należy zmienić z powrotem po aktualizacji / wygenerowaniu. Zawsze to potwierdzam, sprawdzając EDMX po gorzkich doświadczeniach.
Richard Harrison,
ta poprawka nie działa dla mnie? forums.asp.net/p/1770522/4838628.aspx/ ...
Welsh King
Jeśli tak się dzieje w LightSwitch, zobacz mój post na blogu, który wyjaśnia, jak to naprawić w pliku lsml (ponieważ nie ma bezpośredniego dostępu do pliku edmx w LS): lightswitchcentral.net.au/Blog/tabid/83/EntryId/27/ …
Yann Duran,
To jedyne rozwiązanie, ale powinieneś być świadomy, że musisz to zrobić za każdym razem, gdy zmieniasz edmx, ponieważ zmieni się sam
Dave Hogan
11

Szybki podgląd linii:

<Schema Namespace="Foobar.Store" Alias="Self" Provider="System.Data.SqlClient" ProviderManifestToken="2005" >
Jason
źródło
10

Jest to bardzo frustrujące i jestem zaskoczony, że MS zdecydowało się tego nie robić, abyś mógł kierować na daną wersję SQL. Aby upewnić się, że celujemy w rok 2005, napisałem prostą aplikację konsolową i wywołałem ją w kroku PreBuild.

Etap kompilacji wstępnej wygląda następująco:

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

Kod jest tutaj:

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);
            }
        }
    }
}
Vance Kessler
źródło
@ Vance bardzo dziękuję, doskonale. Trochę wolno, ponieważ mam trzy pliki edmx, które muszę zmienić, więc mogę dodać konfigurację rozwiązania tylko po to, aby przywrócić ją po wdrożeniu i usunąć ją ze zwykłej kompilacji. Opublikuje teraz odpowiedź z informacją o używaniu tego przydatnego narzędzia w BeforeBuild (lub AfterBuild) zamiast przed kompilacją. Bardzo cenione.
MemeDeveloper
3

Korzystając z przydatnej aplikacji konsolowej @ Vance powyżej, użyłem następującego zdarzenia jako zdarzenia 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>

Jest to bardzo przydatne, ponieważ pozwala uniknąć irytującego ponownego wdrażania. Dzięki za udostępnienie Vance.

Dodałem TF.exe do folderu rozwiązania biblioteki i to pomaga, ponieważ mogę teraz sprawdzić pliki edmx przed próbą ich edycji, jako część kompilacji. Dodałem również to z warunkami, więc ustawia się na 2005 rok dla wdrożeń na serwerze i powrót do 2008 roku dla konfiguracji sln maszyny Dev. Wspomnij również, że musisz dodać aktualne pliki SetEdmxSqlVersion.exe (i .pdb) do folderu Library (lub gdziekolwiek chcesz zachować te bity).

Bardzo dziękuję @ Vance. Naprawdę schludny, ogromna oszczędność czasu, a moje kompilacje są całkowicie zautomatyzowane i bezbolesne :)

MemeDeveloper
źródło
2

Miałem podobny problem z 2012 i 2008. Można go rozwiązać za pomocą zdarzenia BeforeBuild przy użyciu XmlPeek i 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>

Jeśli nie lubisz automatycznej zamiany, możesz po prostu zamienić zadanie XmlPoke na zadanie błędu.

Edgar
źródło
Jest to znacznie lepsze niż używanie zewnętrznego pliku wykonywalnego, umożliwia MSBuild wewnętrzną obsługę wszystkich fantazyjnych elementów. Wszystko to można łatwo połączyć za pomocą CallTargetwarunkowych zadań docelowych przed kompilacją w zależności od konfiguracji publikowania / kompilacji. (Zmiana EG tylko podczas wdrażania w środowisku sql2005)
admalledd
1

Z korzyścią dla osób, które napotykają ten sam problem, ale używają Code First , zapoznaj się z moją odpowiedzią tutaj, aby dowiedzieć się, jak zmienić ProviderManifestTokenw Code First. Polega na DbModelBuilderręcznym utworzeniu DbProviderInfoinstancji i przekazaniu jej (z odpowiednim tokenem) podczas wywoływania metody konstruktora modelu Build.

sinelaw
źródło
Myślę, że zestaw parametrów Type System Version=SQL Server 2005połączenia może również działać
code4j
0

Lepszym rozwiązaniem dla mnie jest zamiast ręcznej edycji pliku EDMX wystarczy otworzyć edmx w trybie projektowania iw menu kontekstowym „Uaktualnij model z bazy danych…”. Musisz oczywiście wskazywać właściwą wersję SQL, cokolwiek to jest dla Ciebie.

Marek
źródło
1
Myślę, że to jest problem OP - opracował w oparciu o lokalny SQL 2008, ale potem wdrożył do SQL 2005.
StuartLC
Działa to, chyba że nie masz dostępu do instancji SQL 2005.
Darcy
1
Ogromną wadą jest to, że jest to krok ręczny, przez co zostanie zapomniany.
Jowen
0

Wystąpił ten błąd w SQL2005 v.3, gdzie nie było go w SQL2005 v.4.

Dodanie SQL2005 do parametrów połączenia rozwiązało nasz konkretny problem.

Nie zidentyfikowaliśmy jeszcze przyczyny i nie chcieliśmy modyfikować kodu, aby udostępnić token zgodnie z powyższym rozwiązaniem (problem pojawił się podczas wdrażania).

Brian H.
źródło