118

我已经针对 2008 数据库构建了一个实体框架模型。对于 2008 数据库,一切正常。当我尝试更新 2005 数据库上的实体时,我收到此错误。

使用的 SQL Server 版本不支持数据类型 'datetime2

我在构建数据库时特别没有使用任何 2008 功能。我在代码中找不到对 datetime2 的任何引用。而且,是的,该列在数据库中被定义为“日期时间”。

4

8 回答 8

189

一个快速的谷歌向我指出了解决方案的样子。

在文件编辑器中打开您的 EDMX(或在 Visual Studio 中“打开方式...”并选择 XML 编辑器)。在顶部,您会找到存储模型,它有一个属性 ProviderManifestToken。这应该具有值 2008。将其更改为 2005,重新编译,一切正常。

注意:每次从数据库更新模型时都必须这样做。

于 2008-11-25T06:31:11.277 回答
11

快速查看线路:

<Schema Namespace="Foobar.Store" Alias="Self" Provider="System.Data.SqlClient" ProviderManifestToken="2005" >
于 2010-02-05T23:46:29.000 回答
10

这非常令人沮丧,我很惊讶 MS 决定不这样做,以便您可以针对给定的 SQL 版本。为了确保我们的目标是 2005,我编写了一个简单的控制台应用程序并在 PreBuild 步骤中调用它。

预构建步骤如下所示:

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

代码在这里:

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);
            }
        }
    }
}
于 2012-01-06T20:55:23.143 回答
3

使用上面的@Vance 方便的控制台应用程序,我将以下内容用作 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>

这非常方便,可以避免烦人的重新部署。感谢分享万斯。

我已将 TF.exe 添加到库解决方案文件夹中,这很有帮助,因为我现在可以在尝试编辑它们之前检查 edmx 文件,作为构建的一部分。此外,我还添加了条件,以便将其设置为 2005 用于部署到服务器,并设置为 2008 用于开发机器 sln 配置。还要提一下,您需要将实际的 SetEdmxSqlVersion.exe(和 .pdb)文件添加到库文件夹(或您想要保留这些位的任何其他位置)。

非常感谢@Vance。非常整洁,节省大量时间,并使我的构建完全自动化且无痛:)

于 2012-03-28T20:07:24.213 回答
2

2012 年与 2008 年有类似的问题。它可以通过使用 XmlPeek 和 XmlPoke 的 BeforeBuild 事件来解决:

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

如果您不喜欢自动替换,您可以简单地将 XmlPoke 任务替换为错误任务。

于 2016-03-08T12:10:51.443 回答
1

为了让遇到相同问题但使用Code First的人受益,请在此处查看我的回答,了解如何更改ProviderManifestTokenCode First 中的内容。它涉及在调用模型构建器的方法时DbModelBuilder手动创建一个实例并传递一个DbProviderInfo实例(使用适当的令牌) 。Build

于 2012-08-21T18:22:27.287 回答
0

对我来说更好的解决方案不是手动编辑 EDMX 文件,而是在设计模式和上下文菜单“从数据库更新模型...”中打开 edmx。当然,无论这对您来说是什么,您都必须指向正确的 SQL 版本。

于 2011-03-30T11:29:53.483 回答
0

我们在 SQL2005 v.3 上遇到了这个错误,而在 SQL2005 v.4 上没有。

将 SQL2005 添加到连接字符串解决了我们的特定问题。

我们尚未确定原因,也不想修改代码以提供上述解决的令牌(部署期间出现的问题)。

于 2018-02-05T18:12:01.703 回答