Ошибка '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 })