我已经针对2008数据库构建了一个实体框架模型 . 一切都适用于2008数据库 . 当我尝试更新2005数据库上的实体时,我收到此错误 .
The version of SQL Server in use does not support datatype 'datetime2
我在构建数据库时没有使用任何2008功能 . 我在代码中找不到对datetime2的任何引用 . 并且,是的,该列在数据库中被定义为“datetime” .
一个快速的谷歌指向我看起来像solution .
在文件编辑器中打开EDMX(或在Visual Studio中“以...打开”并选择XML编辑器) . 在顶部,您将找到存储模型,它具有属性ProviderManifestToken . 这应该具有值2008.将其更改为2005,重新编译,一切正常 .
注意:每次从数据库更新模型时都必须执行此操作 .
快速查看线:
<Schema Namespace="Foobar.Store" Alias="Self" Provider="System.Data.SqlClient" ProviderManifestToken="2005" >
这是非常令人沮丧的,我很惊讶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>
This is super handy, as avoids annoying redeployment. Thanks for sharing Vance.
我已将TF.exe添加到Library解决方案文件夹中,这有助于,因为我现在可以在尝试编辑之前检查edmx文件,作为构建的一部分 . 此外,我添加了条件,因此它设置为2005以便部署到服务器并返回到2008年的Dev机器sln配置 . 另外要提到的是,您需要将实际的SetEdmxSqlVersion.exe(和.pdb)文件添加到Library文件夹(或者您希望保留这些位的任何其他位置) .
非常感谢@Vance . 非常整洁,节省大量时间,让我的构建完全自动化,无痛苦:)
为了使遇到相同问题但使用 Code First 的人员的利益,请查看my answer here,了解如何更改Code First中的 ProviderManifestToken . 它涉及手动创建 DbModelBuilder 并在调用模型构建器的 Build 方法时传递 DbProviderInfo 实例(带有相应的标记) .
ProviderManifestToken
DbModelBuilder
Build
DbProviderInfo
与2012年和2008年有类似的问题 . 可以使用XmlPeek和XmlPoke通过BeforeBuild事件解决:
<Target Name="BeforeBuild"> <XmlPeek XmlInputPath="$(ProjectDir)MyModel.edmx" Namespaces="<Namespace Prefix='edmx' Uri='http://schemas.microsoft.com/ado/2009/11/edmx'/><Namespace Prefix='ssdl' Uri='http://schemas.microsoft.com/ado/2009/11/edm/ssdl'/>" 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="<Namespace Prefix='edmx' Uri='http://schemas.microsoft.com/ado/2009/11/edmx'/><Namespace Prefix='ssdl' Uri='http://schemas.microsoft.com/ado/2009/11/edm/ssdl'/>" Query="/edmx:Edmx/edmx:Runtime/edmx:StorageModels/ssdl:Schema/@ProviderManifestToken" Value="2008"> </XmlPoke> </Target>
如果您不喜欢自动替换,则可以使用Error任务替换XmlPoke任务 .
对我来说更好的解决方案是手动编辑EDMX文件只是在设计模式和上下文菜单“从数据库更新模型......”中打开edmx . 无论如何,你必须指向正确的SQL版本 .
我们在SQL2005 v.3上遇到了这个错误,我们在SQL2005 v.4上没有它 .
将SQL2005添加到连接字符串修复了我们的具体问题 .
我们还没有确定原因,并且不想修改代码以提供上面解决的令牌(在部署期间出现的问题) .
8 回答
一个快速的谷歌指向我看起来像solution .
在文件编辑器中打开EDMX(或在Visual Studio中“以...打开”并选择XML编辑器) . 在顶部,您将找到存储模型,它具有属性ProviderManifestToken . 这应该具有值2008.将其更改为2005,重新编译,一切正常 .
注意:每次从数据库更新模型时都必须执行此操作 .
快速查看线:
这是非常令人沮丧的,我很惊讶MS决定不这样做,所以你可以针对给定的SQL版本 . 为了确保我们的目标是2005年,我编写了一个简单的控制台应用程序并在PreBuild步骤中调用它 .
预建步骤如下所示:
代码在这里:
使用上面的@Vance方便的控制台应用程序,我使用以下内容作为BeforeBuild事件
This is super handy, as avoids annoying redeployment. Thanks for sharing Vance.
我已将TF.exe添加到Library解决方案文件夹中,这有助于,因为我现在可以在尝试编辑之前检查edmx文件,作为构建的一部分 . 此外,我添加了条件,因此它设置为2005以便部署到服务器并返回到2008年的Dev机器sln配置 . 另外要提到的是,您需要将实际的SetEdmxSqlVersion.exe(和.pdb)文件添加到Library文件夹(或者您希望保留这些位的任何其他位置) .
非常感谢@Vance . 非常整洁,节省大量时间,让我的构建完全自动化,无痛苦:)
为了使遇到相同问题但使用 Code First 的人员的利益,请查看my answer here,了解如何更改Code First中的
ProviderManifestToken
. 它涉及手动创建DbModelBuilder
并在调用模型构建器的Build
方法时传递DbProviderInfo
实例(带有相应的标记) .与2012年和2008年有类似的问题 . 可以使用XmlPeek和XmlPoke通过BeforeBuild事件解决:
如果您不喜欢自动替换,则可以使用Error任务替换XmlPoke任务 .
对我来说更好的解决方案是手动编辑EDMX文件只是在设计模式和上下文菜单“从数据库更新模型......”中打开edmx . 无论如何,你必须指向正确的SQL版本 .
我们在SQL2005 v.3上遇到了这个错误,我们在SQL2005 v.4上没有它 .
将SQL2005添加到连接字符串修复了我们的具体问题 .
我们还没有确定原因,并且不想修改代码以提供上面解决的令牌(在部署期间出现的问题) .