Ошибка 'datetime2' при использовании инфраструктуры сущностей в VS 2010.net 4.0

Получение этой ошибки:

System.Data.SqlClient.SqlException: преобразование типа данных datetime2 в тип данных datetime привело к значению вне диапазона.

Объект My entity все соответствует объектам DB.

Я нашел только одну ссылку на эту ошибку через Google:

Результат Google

Прочитав это, я помню, что мы добавили 2 поля, а затем обновили модель сущности из VS 2010. Я не уверен, что он подразумевает под "ручной кодировкой" различий. Я не вижу.

Все, что я делаю в коде, это заполнение объекта сущности, а затем сохранение. (Я также заполняю новые поля в коде). Я заполнил поле даты DateTime.Now..

Важная часть кода такова: ctx.SaveChanges(SaveOptions.AcceptAllChangesAfterSave);

База данных - это SQL Server 2008.

Мысли?

Остальная часть ошибки:

в System.Data.Mapping.Update.Internal.UpdateTranslator.Update(IEntityStateManager stateManager, адаптер IEntityAdapter) в System.Data.EntityClient.EntityAdapter.Update(IEntityStateManager entityCache) в System.Data.Objects.ObjectContext.SaveChanges(опции SaveOptions) в SafariAdmin.Site.WebServices.SpeciesPost.SaveOrUpdateSpecies(String sid, String fieldName, String authToken) в SpeciesPost.svc.cs: строка 58 в SafariAdmin.TestHarness.Tests.Site.WebServices.SpeciesPostSVC_Tester.SaveNewSpecies() в SpeciesPostSVC_Tester.cs: строка 33 --SqlException в System.Data.SqlClient.SqlConnection.OnError(исключение SqlException, Boolean breakConnection) в System.Data.SqlClient.SqlInternalConnection.OnError(исключение SqlException, логическое breakConnection) в System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning() в System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj) в System.Data.SqlClient.SqlDataReader.ConsumeMetaData() в System.Data.SqlClient.SqlDataReader.get_MetaData() в System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString) в System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async) в System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, метод String, результат DbAsyncResult) в System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, метод String) в System.Data.SqlClient.SqlCommand.ExecuteReader(поведение CommandBehavior, метод String) в System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(поведение CommandBehavior) в System.Data.Common.DbCommand.ExecuteReader(поведение CommandBehavior) в System.Data.Mapping.Update.Internal.DynamicUpdateCommand.Execute(транслятор UpdateTranslator, соединение EntityConnection, словарь 2 identifierValues, List 1 сгенерированныеValues) в System.Data.Mapping.Update.Internal.UpdateTranslator.Update(IEntityStateManager stateManager, адаптер IEntityAdapter)

Ответ 1

Entity framework обрабатывает все даты как Datetime2, поэтому, если ваши поля в базе данных являются Datetime, это может быть проблемой. У нас была та же проблема, и из того, что мы обнаружили, заполнение всех полей даты и изменение типа данных, являются наиболее распространенными решениями

Ответ 2

Если вы используете Code First, вы должны объявить любое необязательное свойство DateTime как DateTime? или Nullable<DateTime>. Устранение объектов DateTime может вызвать проблемы.

Если свойство является нулевым в базе данных и стандартным DateTime в коде (не DateTime?), ADO.NET отправит команду вставки с датой 0001-01-01 (не NULL), но минимальное значение SQL DateTime составляет 1753-01-01, что вызывает ошибку. Если ваше свойство DateTime в коде имеет значение NULL (например, DateTime? или Nullable<DateTime>), команда insert попытается вставить NULL вместо даты вне диапазона.

Ответ 3

Используйте этот SQL script, чтобы преобразовать все столбцы из datetime в datetime2. Он пропускает все таблицы, содержащие "aspnet" для вашего удобства.

DECLARE @SQL AS NVARCHAR(1024)
DECLARE @TBL AS NVARCHAR(255)
DECLARE @COL AS NVARCHAR(255)
DECLARE @NUL AS BIT

DECLARE CUR CURSOR FAST_FORWARD FOR
    SELECT  SCHEMA_NAME(t.schema_id)+'.'+t.name, c.name, c.is_nullable
    FROM    sys.tables AS t
    JOIN    sys.columns c ON t.object_id = c.object_id
    JOIN    information_schema.columns i ON i.TABLE_NAME = t.name 
                                        AND i.COLUMN_NAME = c.name
    WHERE   i.data_type = 'datetime' and t.name not like '%aspnet%'

    ORDER BY t.name, c.name

OPEN CUR
FETCH NEXT FROM CUR INTO @TBL, @COL, @NUL
WHILE @@FETCH_STATUS = 0
BEGIN
    SELECT @SQL = 'ALTER TABLE ' + @TBL 
        + ' ALTER COLUMN [' + @COL + '] datetime2' 
        + (CASE WHEN @NUL=1 THEN '' ELSE ' NOT' END) + ' NULL;'
    EXEC sp_executesql @SQL
    FETCH NEXT FROM CUR INTO @TBL, @COL, @NUL
END

CLOSE CUR;
DEALLOCATE CUR;

Это работает для меня!

Ответ 4

Другим возможным решением является установка типа столбца sql поля в datetime2. это можно сделать с помощью fluentapi.

Property(x => x.TheDateTimeField)
   .HasColumnType("datetime2");

Примечание. Это решение для SQL Server 2008 вверх, так как datetime2 недоступно для SQL Server 2005 или ниже.

Ответ 5

У меня была такая же проблема и решить ее, поместив атрибут [Column(TypeName = "datetime2")] в соответствующие свойства, например, ниже образца:

 [Column(TypeName = "datetime2")]
 public DateTime? PropertyName { get; set; }

Ответ 6

Я знаю, что это старый вопрос, но, поскольку я искал здесь, кто-то другой мог сделать то же самое;-) Для тех, которые меняются с DateTime на DateTime2, не является вариантом (как для пользователей SQL2005), я думаю, что в большинстве случаев более разумно заполнять поля, оставленные пустыми, с чем-то вроде (DateTime)System.Data.SqlTypes.SqlDateTime.MinValue
а не с DateTime.now, так как его легче распознать как "псевдо-нулевое" значение (и если нужно преобразовать его в реальный null в частичном классе объекта-отца)

Ответ 7

При первом использовании кода структуры Entity объявите его следующим образом:

public Nullable<System.DateTime> LastLogin { get; set; }

Ответ 8

Есть ли свойство ModifiedTime в вашей сущности, которое обновляется только на стороне базы данных? Если это так, вы должны использовать DatabaseGeneratedOption.Computed(для EF CodeFirst). Также посетите fooobar.com/questions/93804/...

Спасибо.

Ответ 9

У нас была такая же проблема. Это было связано с версией mssql. Мы сделали это над всеми нашими версиями с помощью этого метода.

Откройте файл edmx с помощью редактора xml. Найдите эту строку в верхней части файла

<Schema Namespace="XXXXX.Store" Alias="Self" Provider="System.Data.SqlClient" ProviderManifestToken="2008"

Заменить 2008 год на 2005 год Сохраните файл, перекомпилируйте проект.

Надеюсь, что это поможет кому-то еще в футуре.

Я только пробовал это решение с помощью dbfirst approche.

Ответ 10

Все, что подходит в datetime, будет соответствовать типу данных datetime2, наоборот, это не так, вы можете придерживаться даты января 1500 года в типе данных datetime2, но datetime возвращается только к 1753, столбец datetime2 может идти назад до пути к году 1. Я бы проверил, какая дата min, которую вы проходите, и если в ваших таблицах есть столбцы типа данных datetime2 или datetime

Ответ 11

После попытки решить эту проблему в течение нескольких дней я использовал DateTime? как тип данных в моей модели с Entity Framework Code-First вместо DateTime.

Ответ 12

Убедитесь, что ни одно из ненулевых полей в БД (datetime) не указано при вставке/обновлении. У меня была такая же ошибка и при вставке значений в те поля datetime проблема была решена. Это происходит, если непустым полям datetime не присвоено правильное значение.

Ответ 13

У меня была такая же проблема в моем приложении ASP.Net MVC.

В моем приложении было два класса моделей, у которых были свойства DateTime.

при исследовании я заметил, что свойство DateTime для одной модели имеет значение NULL, т.е. для того, чтобы присвоить ему дату необязательного свойства Birth

у другой модели было свойство DateTime с обязательной аннотацией данных (ошибка возникает при сохранении этой модели)

мое приложение сначала является кодом, поэтому я решил проблему, установив тип данных как DateTime2

[Column(TypeName="datetime2")] 

то я выполнил миграцию в консоли диспетчера пакетов.

Ответ 14

Simple. В коде сначала укажите тип DateTime для DateTime?. Таким образом, вы можете работать с нулевым типом DateTime в базе данных.

Ответ 15

Это следует из ответа stepanZ... Я получил эту ошибку при использовании Entity Framework Code First с AutoMapper.

При настройке AutoMapping мы имеем поля createddt, updateddt, createdby и updatedby, которые автоматически устанавливаются в нашей функции public override int SaveChanges(). При этом вам нужно обеспечить, чтобы эти поля игнорировались с помощью AutoMapper, иначе база данных будет обновляться с помощью null для этих полей, если они не будут отправлены из View.

Моя проблема заключалась в том, что я неправильно поставил источник и место назначения, поэтому стараюсь игнорировать поля при установке ViewModel, а не при установке Model.

Mapping выглядел так, когда я получил эту ошибку (примечание: cfg.CreateMap<Source, Destination>() на второй строке отображает Model на ViewModel и устанавливает Ignore())

cfg.CreateMap<EventViewModel, Event>();
cfg.CreateMap<Event, EventViewModel>()
    .ForMember(dest => dest.CreatedBy, opt => opt.Ignore())
    .ForMember(dest => dest.CreatedDt, opt => opt.Ignore())
    .ForMember(dest => dest.UpdatedBy, opt => opt.Ignore())
    .ForMember(dest => dest.UpdatedDt, opt => opt.Ignore());

Источником и адресатом следует игнорировать для отображения из ViewModel To Model (примечание: приведенный ниже код верен, где Ignore() помещен против отображения для ViewModel в Model)

cfg.CreateMap<Event, EventViewModel>();
cfg.CreateMap<EventViewModel, Event>()
    .ForMember(dest => dest.CreatedBy, opt => opt.Ignore())
    .ForMember(dest => dest.CreatedDt, opt => opt.Ignore())
    .ForMember(dest => dest.UpdatedBy, opt => opt.Ignore())
    .ForMember(dest => dest.UpdatedDt, opt => opt.Ignore());

Ответ 16

Два решения:

  • Объявите свойства в своем классе, как показано ниже, и создайте базу данных обновлений:

    public DateTime? MyDate {get; set;}
    
  • Или установите дату для свойства в методе Seed, который заполняет базу данных, нет необходимости в базе данных обновлений:

    context.MyClass.AddOrUpdate(y => y.MyName,new MyClass { MyName = "Random", MyDate= DateTime.Now })