使用 SQL Server 2008 和 SQL Server 2005 和日期时间

Posted

技术标签:

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

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

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

我在构建数据库时特别没有使用任何 2008 功能。我在代码中找不到对 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 添加到连接字符串解决了我们的特定问题。

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

【讨论】:

以上是关于使用 SQL Server 2008 和 SQL Server 2005 和日期时间的主要内容,如果未能解决你的问题,请参考以下文章

安装SQL SERVER 2008,出现“查找sql server 2008安装媒体”的问题

如何用SQL SERVER 2005连接SQL SERVER 2008

sql server 2008 r2 sp1 怎么看版本

sql server2008升级到2008 R2出现问题

从开发人员的 POV 看 SQL Server 2008 和 SQL Server 2008 R2 之间的差异

sql server2008的组件主要是哪些?