Использование SQL Server 2008 и SQL Server 2005 и даты и времени

118

Я построил модель структуры сущностей на основе базы данных 2008 года. Все работает нормально с базой данных 2008 года. Когда я пытаюсь обновить объект в базе данных 2005 года, я получаю эту ошибку.

Используемая версия SQL Server не поддерживает тип данных datetime2.

Я специально не использовал какие-либо функции 2008 года при создании базы данных. Я не могу найти в коде ссылки на datetime2. И, да, столбец определяется в базе данных как «datetime».

Monroecheeseman
источник

Ответы:

189

Быстрый гугл указывает мне, что похоже на решение .

Откройте EDMX в редакторе файлов (или «откройте с…» в Visual Studio и выберите XML Editor). Вверху вы найдете модель хранилища и у нее есть атрибут ProviderManifestToken. Он должен иметь значение 2008. Измените его на 2005, перекомпилируйте, и все заработает.

ПРИМЕЧАНИЕ. Вам придется делать это каждый раз, когда вы обновляете модель из базы данных.

Ричард Харрисон
источник
2
Я по ошибке проголосовал за это, отменил это, но теперь не могу сделать то, что действительно хотел, а именно проголосовать за это! Спасибо, что нашли проблему. Если я правильно понимаю, изменилось ли значение с 2005 на 2008 из-за обновления модели из базы данных, где база данных - это база данных SQL 2008? В моей среде на моей машине разработчика установлен SQL 2008, а в тестовой - 2005 (в производственной среде тоже). Правильно ли я предполагаю, что это будет продолжаться до тех пор, пока мы не перейдем к 2008 году?
jamiebarrow
Я обычно устанавливаю это значение 2005, это производственная база данных; Я использую 2008 год для разработки. Версия 2008 обратно совместима, так что никаких проблем. Также это должно быть изменено обратно после обновления / генерации. Я всегда подтверждаю это, проверяя EDMX после горького опыта.
Ричард Харрисон,
это исправление не работает для меня ?? forum.asp.net/p/1770522/4838628.aspx/…
Король Уэльса
Если это происходит в LightSwitch, см. Мое сообщение в блоге, в котором объясняется, как исправить это в файле lsml (поскольку в LS нет прямого доступа к файлу edmx): lightswitchcentral.net.au/Blog/tabid/83/EntryId/27/ …
Янн Дюран
Это единственное решение, но вы должны знать, что вам нужно делать это каждый раз, когда вы вносите поправки в edmx, поскольку он сам вернется в исходное состояние
Дэйв Хоган,
11

Быстрый просмотр линии:

<Schema Namespace="Foobar.Store" Alias="Self" Provider="System.Data.SqlClient" ProviderManifestToken="2005" >
Джейсон
источник
10

Это очень расстраивает, и я удивлен, что 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) вместо предварительной сборки. Большое спасибо.
MemeDeveloper
3

Используя удобное консольное приложение @ 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.exe (и .pdb) в папку библиотеки (или в другое место, где вы хотите сохранить эти биты).

Большое спасибо @Vance. Действительно аккуратно, значительно экономит время и делает мои сборки полностью автоматизированными и безболезненными :)

MemeDeveloper
источник
2

Была аналогичная проблема с 2012 по сравнению с 2008 годом. Ее можно решить с помощью события BeforeBuild, используя XmlPeek и 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 задачей с ошибкой.

Эдгар
источник
Это намного лучше, чем использование внешнего исполняемого файла, позволяет MSBuild обрабатывать все причуды изнутри. Все это можно легко связать с помощью CallTargetусловных целевых задач предварительной сборки в зависимости от конфигураций публикации / сборки. (EG изменяется только при развертывании в среде sql2005)
добавлено
1

Для удобства людей, которые сталкиваются с той же проблемой, но используют Code First , ознакомьтесь с моим ответом здесь о том, как изменить ProviderManifestTokenв Code First. Он включает создание DbModelBuilderвручную и передачу DbProviderInfoэкземпляра (с соответствующим токеном) при вызове Buildметода построителя модели .

sinelaw
источник
Я думаю, что набор Type System Version=SQL Server 2005в строке подключения также может работать
code4j
0

Лучшее решение для меня - вместо ручного редактирования файла EDMX просто открыть edmx в режиме проектирования и в контекстном меню «Обновить модель из базы данных ...». Конечно, вы должны указывать на правильную версию SQL, что бы это ни было для вас.

Marek
источник
1
Я думаю, что это проблема OP - он разработал для локального SQL 2008, но затем развернул на SQL 2005.
StuartLC
Это работает, если у вас нет доступа к экземпляру SQL 2005.
Дарси
1
Огромным недостатком является то, что это ручной шаг, и поэтому о нем забудут.
Jowen
0

У нас была эта ошибка на SQL2005 v.3, где у нас ее не было на SQL2005 v.4.

Добавление SQL2005 в строку подключения устранило нашу конкретную проблему.

Мы еще не определили, почему, и не хотели изменять код для предоставления токена, как было решено выше (проблема проявляется во время развертывания).

Брайан Х
источник