Uso de SQL Server 2008 y SQL Server 2005 y fecha y hora

118

Construí un modelo de marco de entidad contra una base de datos de 2008. Todo funciona bien contra la base de datos de 2008. Cuando intento actualizar la entidad en una base de datos de 2005, aparece este error.

La versión de SQL Server en uso no admite el tipo de datos 'datetime2

Específicamente, no usé ninguna característica de 2008 cuando construí la base de datos. No puedo encontrar ninguna referencia a datetime2 en el código. Y sí, la columna está definida como "fecha y hora" en la base de datos.

Monroecheeseman
fuente

Respuestas:

189

Un rápido google me señala lo que parece ser la solución .

Abra su EDMX en un editor de archivos (o "abra con ..." en Visual Studio y seleccione XML Editor). En la parte superior encontrará el modelo de almacenamiento y tiene un atributo ProviderManifestToken. Esto debe tener el valor 2008. Cámbielo a 2005, vuelva a compilar y todo funcionará.

NOTA: Deberá hacer esto cada vez que actualice el modelo desde la base de datos.

Richard Harrison
fuente
2
He votado en contra por error, deshice eso, pero ahora no puedo hacer lo que realmente quería hacer, ¡que es votar a favor! Gracias por encontrar el problema. Si entiendo correctamente, ¿el valor cambia de 2005 a 2008 debido a la actualización del modelo de la base de datos, donde la base de datos es una base de datos SQL 2008? En mi entorno, mi máquina de desarrollo tiene SQL 2008, pero el entorno de prueba tiene 2005 (que también tiene producción). Hasta que migremos a 2008, ¿tengo razón al suponer que esto seguirá ocurriendo?
jamiebarrow
Generalmente establezco esto en 2005, que es la base de datos de producción; Estoy usando 2008 para el desarrollo. 2008 es compatible con versiones anteriores, por lo que no hay problemas. Además, esto se volverá a cambiar después de una actualización / generación. Siempre valido esto al registrar el EDMX después de una amarga experiencia.
Richard Harrison
esta solución no funciona para mí? forums.asp.net/p/1770522/4838628.aspx/…
Welsh King
Si esto sucede en LightSwitch, vea la publicación de mi blog que explica cómo solucionarlo en el archivo lsml (ya que no hay acceso directo al archivo edmx en LS): lightswitchcentral.net.au/Blog/tabid/83/EntryId/27/ …
Yann Duran
Es la única solución, pero debe tener en cuenta que debe hacer esto cada vez que modifique el edmx, ya que se revertirá solo
Dave Hogan
11

Vista rápida de la línea:

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

Esto es muy frustrante y me sorprende que MS haya decidido no hacerlo para poder apuntar a una determinada versión de SQL. Para asegurarme de que estamos apuntando a 2005, escribí una aplicación de consola simple y la llamé en un paso PreBuild.

El paso previo a la compilación se ve así:

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

El código está aquí:

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
fuente
@Vance muchas gracias, perfecto. Un poco lento, ya que tengo tres archivos edmx que necesito cambiar, por lo que podría agregar una configuración de solución solo para revertir después de una implementación y eliminarla de la compilación habitual. Publicará una respuesta ahora con la información para usar esta útil herramienta en un BeforeBuild (o AfterBuild) en lugar de una pre-compilación. Muy apreciado.
MemeDeveloper
3

Usando la práctica aplicación de consola de @ Vance anterior, usé lo siguiente como un 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>

Esto es muy útil, ya que evita la molesta redistribución. Gracias por compartir Vance.

Agregué TF.exe a la carpeta de la solución de la biblioteca y esto ayuda, ya que ahora puedo verificar los archivos edmx antes de intentar editarlos, como parte de la compilación. También agregué esto con condiciones, de modo que se establezca en 2005 para implementaciones en el servidor y en 2008 para las configuraciones sln de la máquina Dev. También para mencionar que debe agregar los archivos SetEdmxSqlVersion.exe (y .pdb) reales a la carpeta de la biblioteca (o en cualquier otro lugar donde desee mantener estos bits).

Muchas gracias @Vance. Realmente ordenado, ahorra mucho tiempo y mantiene mis compilaciones totalmente automatizadas y sin dolor :)

MemeDesarrollador
fuente
2

Tuve un problema similar con 2012 vs. 2008. Se puede resolver con un evento BeforeBuild usando XmlPeek y 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 no le gusta el reemplazo automático, simplemente puede reemplazar la tarea XmlPoke con una tarea Error.

Edgar
fuente
Esto es mucho mejor que usar un ejecutable externo, permite a MSBuild manejar toda la fantasía internamente. Todo esto se puede encadenar fácilmente a través de CallTargettareas de destino condicionales previas a la compilación según las configuraciones de publicación / compilación. (EG solo cambia cuando se implementa en un entorno sql2005)
admalledd
1

Para el beneficio de las personas que se encuentran con el mismo problema pero que usan Code First , consulte mi respuesta aquí sobre cómo cambiar ProviderManifestTokenen Code First. Implica crear un DbModelBuildermanual y pasar una DbProviderInfoinstancia (con el token apropiado) al llamar al Buildmétodo del generador de modelos .

sinelaw
fuente
Creo que la Type System Version=SQL Server 2005cadena de conexión establecida también puede funcionar
code4j
0

Una mejor solución para mí es, en lugar de editar manualmente el archivo EDMX, simplemente abrir edmx en el modo de diseño y en el menú contextual "Actualizar modelo desde la base de datos ...". Tienes que apuntar a la versión correcta de SQL, por supuesto, sea lo que sea para ti.

Marek
fuente
1
Creo que este es el problema de OP: se desarrolló contra un SQL 2008 local pero luego lo implementó en SQL 2005.
StuartLC
Esto funciona a menos que no tenga acceso a una instancia de SQL 2005.
Darcy
1
Una gran desventaja es que es un paso manual y, por lo tanto, se olvidará.
Jowen
0

Tuvimos este error en SQL2005 v.3, donde no lo teníamos en SQL2005 v.4.

Agregar SQL2005 a la cadena de conexión solucionó nuestro problema específico.

Aún no hemos identificado por qué y no queríamos modificar el código para proporcionar el token como se resolvió anteriormente (problema manifestado durante la implementación).

Brian H
fuente