Использование SQL Server 2008 и SQL Server 2005, а также дата и время
Я построил модель Entity framework для базы данных 2008 года. Все работает нормально против базы данных 2008 года. Когда я пытаюсь обновить сущность в базе данных 2005 года, я получаю эту ошибку.
The version of SQL Server in use does not support datatype 'datetime2
Я специально не использовал никаких функций 2008 года, когда я построил базу данных. Я не могу найти ссылку на datetime2 в коде. И, да столбец определяется как" datetime " в базе данных.
8 ответов:
быстрый google указывает мне на то, что выглядит как решение.
откройте EDMX в Редакторе файлов (или "открыть с помощью..." в Visual Studio и выберите редактор XML). В верхней части вы найдете модель хранения, и она имеет атрибут ProviderManifestToken. Это должно иметь значение 2008 года. Измените это на 2005, перекомпилируйте и все работает.
Примечание: вам придется делать это каждый раз, когда вы обновить модель из базы данных.
быстрый просмотр строку:
<Schema Namespace="Foobar.Store" Alias="Self" Provider="System.Data.SqlClient" ProviderManifestToken="2005" >
Это очень расстраивает, и я удивлен, что MS решила не делать этого, чтобы вы могли нацелиться на данную версию SQL. Чтобы убедиться, что мы нацелены на 2005 год, я написал простое консольное приложение и вызвал его на этапе предварительной сборки.
предварительный шаг выглядит следующим образом:
$(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>
это очень удобно,так как позволяет избежать раздражающего перераспределения. Спасибо, что поделился Вэнсом.
Я добавил TF.exe в папку решения библиотеки, и это помогает, так как теперь я могу проверить файлы edmx, прежде чем пытаться их редактировать, как часть сборки. Также я добавил это с условиями, так что он устанавливает в 2005 для развертывания на сервере и обратно в 2008 для конфигураций sln машины Dev. Кроме того, чтобы упомянуть, что вам нужно добавить фактический SetEdmxSqlVersion.исполняемые (и .pdb) файл(ы) в папку библиотеки (или где еще вы хотите сохранить эти биты).
большое спасибо @Vance. действительно аккуратный, массивный экономия времени и держит мои сборки полностью автоматизированы и безболезненно:)
в интересах людей, которые сталкиваются с той же проблемой, но используют Код "Первый"!--6-->, проверьте мой ответ здесь о том, как изменить
ProviderManifestToken
сначала в коде. Это включает в себя созданиеDbModelBuilder
вручную и передаетDbProviderInfo
экземпляр (с соответствующим маркером) при вызове конструктора моделейBuild
метод.
была аналогичная проблема с 2012 по сравнению с 2008 годом. Его можно решить с помощью события BeforeBuild с помощью XmlPeek и XmlPoke:
<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>
Если вам не нравится автоматическая замена, вы можете просто заменить задачу XmlPoke на задачу с ошибкой.