Использование SQL Server 2008 и SQL Server 2005 и дата и время
Я построил модель структуры сущности на основе базы данных 2008 года. Все работает хорошо с базой данных 2008 года. Когда я пытаюсь обновить сущность в базе данных 2005 года, я получаю эту ошибку.
Используемая версия SQL Server не поддерживает тип данных datetime2
Я специально не использовал никаких функций 2008 года при создании базы данных. Я не могу найти ссылку на datetime2 в коде. И, да, столбец определяется как "дата / время" в базе данных.
8 ответов
Быстрый Google указывает мне на то, что выглядит как решение.
Откройте 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>
Это очень удобно, так как позволяет избежать назойливого передислокации. Спасибо, что поделились Вэнсом.
Я добавил TF.exe в папку решения библиотеки, и это помогает, так как теперь я могу проверить файлы edmx перед тем, как пытаться редактировать их, как часть сборки. Кроме того, я добавил это с условиями, чтобы он был установлен на 2005 для развертываний на сервер и обратно на 2008 для конфигураций SL-машины Dev. Также стоит упомянуть, что вам нужно добавить фактические файлы SetEdmxSqlVersion.exe (и.pdb) в папку "Библиотека" (или где бы вы ни хотели сохранить эти биты).
Большое спасибо @Vance. Действительно аккуратный, экономит время и полностью автоматизирует мои сборки и избавляет от боли:)
В интересах людей, которые сталкиваются с той же проблемой, но используют Code First, ознакомьтесь с моим ответом здесь о том, как изменить 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 на задачу Error.
Лучшее решение для меня - вместо того, чтобы вручную редактировать файл EDMX, просто откройте edmx в режиме разработки и в контекстном меню "Обновить модель из базы данных...". Вы должны указывать на правильную версию SQL, конечно, независимо от того, что это для вас.
У нас была эта ошибка на SQL2005 v.3, где ее не было на SQL2005 v.4.
Добавление SQL2005 в строку подключения решило нашу конкретную проблему.
Мы еще не определили, почему, и не хотели модифицировать код для предоставления токена, как решено выше (проблема проявлялась во время развертывания).