Usando SQL Server 2008 e SQL Server 2005 e data e hora

118

Eu construí um modelo de estrutura de entidade em um banco de dados de 2008. Tudo funciona bem no banco de dados de 2008. Quando tento atualizar a entidade em um banco de dados de 2005, recebo este erro.

A versão do SQL Server em uso não oferece suporte ao tipo de dados 'datetime2

Especificamente, não usei nenhum recurso de 2008 quando criei o banco de dados. Não consigo encontrar nenhuma referência a datetime2 no código. E, sim, a coluna é definida como "data e hora" no banco de dados.

Monroecheeseman
fonte

Respostas:

189

Um rápido google me aponta para o que parece ser a solução .

Abra seu EDMX em um editor de arquivo (ou “abra com…” no Visual Studio e selecione Editor de XML). Na parte superior, você encontrará o modelo de armazenamento e ele possui um atributo ProviderManifestToken. Este deve ter o valor 2008. Mude para 2005, recompile e tudo funciona.

NOTA: Você terá que fazer isso sempre que atualizar o modelo do banco de dados.

Richard Harrison
fonte
2
Eu votei contra isso por engano, desfiz isso, mas agora não posso fazer o que eu realmente queria fazer, que é votar a favor! Obrigado por encontrar o problema. Se bem entendi, o valor muda de 2005 para 2008 devido à atualização do modelo do banco de dados, onde o banco de dados é um banco de dados SQL 2008? No meu ambiente, minha máquina de desenvolvedor tem SQL 2008, mas o ambiente de teste tem 2005 (que também tem produção). Até migrarmos para 2008, estou certo em presumir que isso continuará ocorrendo?
jamiebarrow
Eu geralmente defino isso como 2005, que é o banco de dados de produção; Estou usando 2008 para desenvolvimento. 2008 é compatível com versões anteriores, então sem problemas. Também deve ser alterado novamente após uma atualização / geração. Sempre valido isso ao fazer o check-in no EDMX após uma experiência amarga.
Richard Harrison
essa correção não funciona para mim ?? forums.asp.net/p/1770522/4838628.aspx/…
Rei galês de
Se isso acontecer no LightSwitch, veja minha postagem do blog que explica como consertar no arquivo lsml (já que não há acesso direto ao arquivo edmx no LS): lightswitchcentral.net.au/Blog/tabid/83/EntryId/27/ …
Yann Duran
É a única solução, mas você deve estar ciente de que precisa fazer isso toda vez que alterar o edmx, pois ele se reverterá
Dave Hogan
11

Visão rápida da linha:

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

Isso é muito frustrante e estou surpreso que a MS tenha decidido não fazer isso para que você pudesse ter como alvo uma determinada versão do SQL. Para ter certeza de que estamos visando 2005, escrevi um aplicativo de console simples e chamei-o em uma etapa de Pré-construção.

A etapa de pré-construção se parece com isto:

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

O código está aqui:

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
fonte
@Vance muito obrigado, perfeito. Um pouco lento, como tenho três arquivos edmx que preciso alterar, então posso adicionar uma configuração de solução apenas para reverter após uma implantação e removê-lo da compilação normal. Irá postar uma resposta agora com as informações para usar esta ferramenta útil em um BeforeBuild (ou AfterBuild) em vez de pré-construção. Muito apreciado.
MemeDeveloper
3

Usando o prático aplicativo de console de @Vance acima, usei o seguinte como um 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>

Isso é muito útil, pois evita reimplementação irritante. Obrigado por compartilhar Vance.

Adicionei TF.exe à pasta da solução da Biblioteca e isso ajuda, pois agora posso verificar os arquivos edmx antes de tentar editá-los, como parte da construção. Além disso, acrescentei isso com condições, de modo que seja definido como 2005 para implantações no servidor e de volta para 2008 para as configurações de sln da máquina Dev. Além disso, para mencionar que você precisa adicionar o (s) arquivo (s) SetEdmxSqlVersion.exe (e .pdb) à pasta Biblioteca (ou onde mais você quiser manter esses bits).

Muito obrigado @Vance. Muito legal, grande economia de tempo e mantém minhas compilações totalmente automatizadas e sem dor :)

MemeDeveloper
fonte
2

Tive um problema semelhante com 2012 vs. 2008. Ele pode ser resolvido com um evento BeforeBuild usando 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 você não gosta da substituição automatizada, pode simplesmente substituir a tarefa XmlPoke por uma tarefa Erro.

Edgar
fonte
Isso é muito melhor do que usar um executável externo e permite que o MSBuild trate de todas as fantasias internamente. Tudo isso pode ser facilmente encadeado por meio de CallTargettarefas de destino de pré-construção condicional, dependendo das configurações de publicação / construção. (EG só muda ao implantar em um ambiente sql2005)
admalledd
1

Para o benefício de pessoas que encontram o mesmo problema, mas estão usando o Code First , verifique minha resposta aqui sobre como alterar o ProviderManifestTokenno Code First. Envolve criar DbModelBuildermanualmente e passar uma DbProviderInfoinstância (com o token apropriado) ao chamar o Buildmétodo do construtor de modelo .

sinelaw
fonte
Acho que definir Type System Version=SQL Server 2005na string de conexão também pode funcionar
code4j
0

A melhor solução para mim é em vez de editar manualmente o arquivo EDMX, basta abrir o edmx no modo de design e no menu de contexto "Atualizar modelo do banco de dados ...". Você tem que apontar para a versão correta do SQL, é claro, seja lá o que for isso para você.

Marek
fonte
1
Acho que esse é o problema do OP - ele desenvolveu em um SQL local 2008, mas depois implantou no SQL 2005.
StuartLC
Isso funciona a menos que você não tenha acesso a uma instância do SQL 2005.
Darcy de
1
Uma grande desvantagem é que é uma etapa manual e, portanto, será esquecida.
Jowen
0

Tivemos esse erro no SQL2005 v.3, onde não o tínhamos no SQL2005 v.4.

Adicionar SQL2005 à string de conexão corrigiu nosso problema específico.

Ainda não identificamos o porquê e não queremos modificar o código para fornecer o token conforme resolvido acima (problema manifestado durante a implantação).

Brian H
fonte