Entity Framework 7 не вставляет дату и время

debian entity-framework-core mono sql-server windows

Вопрос

Я использую EntityFramework 7, beta7 и имею следующую сущность:

C #

public class Log
{
    [Column(TypeName ="datetime")]
    public DateTime Date { get; set; }
    ...
}

SQL

CREATE TABLE [dbo].[Logs] (
    [Date] [datetime] NOT NULL,
    ...
)

И я выполняю следующее:

db.Logs.Add(new Log { Date = DateTime.UtcNow });
db.SaveChanges();

Это успешно работает в Windows, но не удается выполнить моно на debian. Тот же SQL-сервер / база данных. Сгенерированный SQL ниже. Обратите внимание на разницу в типе и значении, отображаемом для @p1 :

Windows

exec sp_executesql N'SET NOCOUNT OFF;
INSERT INTO [Logs] ([Browser], [Date], [Exception], [HostAddress], [Level], [Logger], [Message], [Thread], [Url], [Username])
OUTPUT INSERTED.[Id]
VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9);
',N'@p0 nvarchar(max) ,@p1 datetime2(7),@p2 nvarchar(max) ,@p3 nvarchar(max) ,@p4 nvarchar(4000),@p5 nvarchar(4000),@p6 nvarchar(4000),@p7 nvarchar(4000),@p8 nvarchar(max) ,@p9 nvarchar(max) ',@p0=NULL,@p1='2015-09-28 23:02:26.0367851',@p2=NULL,@p3=NULL,@p4=N'INFO',@p5=N'Fanatics.ConsoleApp.Program',@p6=N'Console app test',@p7=N'0',@p8=NULL,@p9=NULL
go

Linux

exec sp_executesql N'SET NOCOUNT OFF;
INSERT INTO [Logs] ([Browser], [Date], [Exception], [HostAddress], [Level], [Logger], [Message], [Thread], [Url], [Username])
OUTPUT INSERTED.[Id]
VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9);
',N'@p0 nvarchar(4000), @p1 char(27), @p2 nvarchar(4000), @p3 nvarchar(4000), @p4 nvarchar(4000), @p5 nvarchar(4000), @p6 nvarchar(4000), @p7 nvarchar(4000), @p8 nvarchar(4000), @p9 nvarchar(4000)',@p0=NULL,@p1='2015-09-28T23:03:21.5561720',@p2=NULL,@p3=NULL,@p4=N'INFO',@p5=N'Fanatics.ConsoleApp.Program',@p6=N'Console app test',@p7=N'0',@p8=NULL,@p9=NULL
go

Ошибка в Linux:

Ошибка конверсии при преобразовании даты и / или времени из символьной строки.

Вопросов

  1. Почему Windows генерирует datetime2 когда тип явно установлен в datetime ?
  2. Версия linux генерирует недопустимый SQL, следовательно, сбой. Как вставлять значения datetime в mono / linux?

Принятый ответ

  1. Тип .NET DateTime имеет более широкий диапазон, чем тип «datetime» сервера SQL. Фактически, .NET DateTime имеет тот же диапазон, что и тип «datetime2» для SQL-сервера, поэтому Entity Framework будет использовать datetime2 (если возможно) всюду при преобразовании DateTime в sql date (как в вашем примере). В этом случае тип столбца таблицы не имеет значения. Вы можете прочитать эту заметку о встречах с дизайнером, где команда EF обсуждает проблему с datetime и datetime2 и решает оставить это как есть (и причины этого).

  2. Mono использует TDS для работы с сервером sql (на основе FreeTDS , и использует довольно устаревшую версию). Эта версия не имеет понятия о типе «datetime2» в sql-сервере, поэтому вместо перехода на новую версию TDS (может быть, это слишком много работа на данный момент), был реализован вид хака, преобразование datetime2 из \ в строку. Теперь datetime2 имеет более высокую точность, чем datetime, поэтому при преобразовании datetime2 в строку и затем преобразовании этой строки в datetime (что делается неявно) вызывает ошибку см. Это легко проверить:

    select cast('2015-09-28T23:03:21.5561720' as datetime2) -- < all fine
    select cast('2015-09-28T23:03:21.5561720' as datetime) -- < error from your question
    

    Вы можете прочитать немного больше об этом здесь .

Вы можете спросить, можете ли вы использовать EF с сервером sql на моно. Ну, вы можете обходным путем, установив ProviderManifestToken в 2005 году в своей EF-модели. Это заставит EF работать с SQL Server 2005, и он не будет использовать datetime2 во всем мире. Но вы потеряете другие типы, которые были добавлены после SQL Server 2005, очевидно, не говоря уже о том, что это грязный взломать.

В качестве побочного примечания - лучше не делайте серьезных разработок на моно с сервером sql. Поставщик сервера Sql в моно заполнен ошибками, а ошибка выше - одна из самых невинных. У этого есть проблемы с нулевыми значениями, проблемами с пулом подключений (этот очень серьезный - если вы тайм-аут на подключении пула соединений - это соединение будет разбито на всю жизнь, а ВСЕ запросы на это соединение не удастся. Hack - удалить соединение из соединения пул, если ваш запрос истекал на нем) и т. д. Большинство этих ошибок известны в течение многих лет и не исправлены. Если у вас есть выбор - просто используйте postgresql, это бесплатно, хорошо, и у меня не было проблем с ним на моно.



Related

Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow
Является ли этот КБ законным? Да, узнайте, почему
Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow
Является ли этот КБ законным? Да, узнайте, почему