【问题标题】:Using SQL Server 2008 and SQL Server 2005 and date time使用 SQL Server 2008 和 SQL Server 2005 和日期时间
【发布时间】:2008-11-25 05:15:35
【问题描述】:

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

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

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

【问题讨论】:

    标签: sql-server-2005 entity-framework sql-server-2008 datetime datetime2


    【解决方案1】:

    一个快速的谷歌将我指向看起来像solution

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

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

    【讨论】:

    • 我错误地投了反对票,取消了那个,但现在不能做我真正想做的事,那就是投票!感谢您发现问题。如果我理解正确,由于从数据库更新模型,值是否从 2005 年更改为 2008 年,其中数据库是 SQL 2008 DB?在我的环境中,我的开发机器有 SQL 2008,但测试环境有 2005(生产环境也有)。在我们迁移到 2008 年之前,我是否认为这种情况会继续发生?
    • 我一般设置为2005,也就是生产数据库;我正在使用 2008 进行开发。 2008 是向后兼容的,所以没有问题。这也将在更新/生成后更改回来。在经历了痛苦的经历后,我总是在签入 EDMX 时验证这一点。
    • 这个修复对我不起作用?? forums.asp.net/p/1770522/4838628.aspx/…
    • 如果在 LightSwitch 中发生这种情况,请参阅我的博客文章,其中解释了如何在 lsml 文件中修复它(因为无法直接访问 LS 中的 edmx 文件):lightswitchcentral.net.au/Blog/tabid/83/EntryId/27/…
    • 这是唯一的解决方案,但您应该知道,每次修改 edmx 时都需要这样做,因为它会自行恢复
    【解决方案2】:

    快速查看线路:

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

    【讨论】:

      【解决方案3】:

      这非常令人沮丧,我很惊讶 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);
                  }
              }
          }
      }
      

      【讨论】:

      • @Vance 非常感谢,完美。有点慢,因为我需要更改三个 edmx 文件,因此可能会添加一个解决方案配置,只是为了在部署后恢复,并将其从通常的构建中删除。现在将发布一个答案,其中包含在 BeforeBuild(或 AfterBuild)而不是预构建中使用这个方便的工具的信息。非常感谢。
      【解决方案4】:

      使用上面@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)文件添加到 Library 文件夹(或您想要保留这些位的任何其他位置)。

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

      【讨论】:

        【解决方案5】:

        在 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 任务替换为错误任务。

        【讨论】:

        • 这比使用外部可执行文件要好得多,允许 MSBuild 在内部处理所有花哨的东西。这一切都可以通过CallTarget 有条件的预构建目标任务轻松链接,具体取决于发布/构建配置。 (EG只在部署到sql2005环境时改变)
        【解决方案6】:

        为了方便遇到相同问题但使用 Code First 的人,请查看my answer here,了解如何在 Code First 中更改 ProviderManifestToken。它涉及在调用模型构建器的Build 方法时手动创建DbModelBuilder 并传递DbProviderInfo 实例(带有适当的令牌)。

        【讨论】:

        • 我认为在连接字符串中设置Type System Version=SQL Server 2005 也可以工作
        【解决方案7】:

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

        【讨论】:

        • 我认为这是 OP 的问题 - 他针对本地 SQL 2008 开发,然后部署到 SQL 2005。
        • 此方法有效,除非您无权访问 SQL 2005 实例。
        • 一个巨大的缺点是这是一个手动步骤,因此会被遗忘。
        【解决方案8】:

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

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

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-10-23
          • 2010-12-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-11-17
          相关资源
          最近更新 更多