使用 SQLServer2008和 SQLServer2005以及日期时间

我已经根据2008年的数据库构建了一个实体框架模型。对于2008数据库,所有工作都正常。当我尝试更新2005数据库上的实体时,会得到这个错误。

The version of SQL Server in use does not support datatype 'datetime2

I specifically did not use any 2008 features when I built the database. I can't find any reference to datetime2 in the code. And, yes the column is defined as "datetime" in the database.

34372 次浏览

一个快速的谷歌指出我什么样子的 解决方案

Open your EDMX in a file editor (or “open with…” in Visual Studio and select XML Editor). At the top you will find the storage model and it has an attribute ProviderManifestToken. This has should have the value 2008. Change that to 2005, recompile and everything works.

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

快速浏览线条:

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

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

这是非常令人沮丧的,我很惊讶 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 的控制台应用程序,我使用以下内容作为一个 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>

这非常方便,避免了烦人的重新部署。谢谢分享 Vance。

我已经将 TF.exe 添加到 Library 解决方案文件夹中,这很有帮助,因为我现在可以在尝试编辑 edmx 文件之前签出它们,作为构建的一部分。此外,我还添加了一些条件,以便将部署到服务器的部署设置为2005,将部署到 Dev 机器的部署设置为回到2008。还要提到的是,您需要添加实际的 SetEdmxSqlVersion.exe (和。Pdb)文件到 Library 文件夹(或者其他您想保存这些位的地方)。

Thanks very much @Vance. Really neat, massive time saver and keeps my builds totally automated and pain free :)

为了让那些遇到同样问题但正在使用 代码优先的人受益,请查看 我的答案就在这里,了解如何在代码优先(Code First)中更改 ProviderManifestToken。它涉及到手动创建一个 DbModelBuilder,并在调用模型构建器的 Build方法时传递一个 DbProviderInfo实例(使用适当的令牌)。

Had a similar problem with 2012 vs. 2008. It can be solved with a BeforeBuild event using XmlPeek and 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>

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

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

Adding SQL2005 to the connection string fixed our specific problem.

我们还没有确定原因,也不想修改代码来提供上面解决的令牌(部署期间出现的问题)。