【问题标题】:Unable to cast object of type 'System.String' to type 'System.DateTime' on datetime literal无法将“System.String”类型的对象转换为日期时间文字上的“System.DateTime”类型
【发布时间】:2019-09-26 05:38:49
【问题描述】:

我们有一个游戏主机 MySQL 数据库,可以运行特定游戏类型的游戏。我有一个 linq 语句,它返回主机 ID、名称和标题 + 在主机上玩的最后一场游戏的开始时间(如果有的话)。

context.HostConfigurations.Select (h => new HostStatus {
                id = h.IdHostConfigurations,
                hostname = h.Hostname,
                gameTitle = h.IdGamesLast.HasValue ? h.LastGameNavigation.GameTypeNavigation.Title : "-",
                gameStart = h.IdGamesLast.HasValue ? h.LastGameNavigation.Gamestart : DateTimeOffset.MinValue,
                gameStartFriendly = h.IdGamesLast.HasValue ? h.LastGameNavigation.Gamestart.ToString ("ddd HH:mm") : "-"
            }).ToList ();

日志输出如下:

INFO: Microsoft.EntityFrameworkCore.Database.Command Executed DbCommand (21ms) [Parameters=[@__nowMinus24Hrs_0='?' (DbType = DateTimeOffset), @__nowMinusTenMinutes_1='?' (DbType = DateTimeOffset)], CommandType='Text', CommandTimeout='30']
SELECT `h`.`idHostConfigurations` AS `id`, `h`.`hostname`, CASE
    WHEN `h`.`idGamesLast` IS NOT NULL
    THEN `h.LastGameNavigation.GameTypeNavigation`.`title` ELSE '-'
END AS `gameTitle`, CASE
    WHEN `h`.`idGamesLast` IS NOT NULL
    THEN `h.LastGameNavigation`.`gamestart` ELSE '0001-01-01 00:00:00.000000'
END AS `gameStart0`, CASE
WHEN `h`.`idGamesLast` IS NOT NULL
    THEN TRUE ELSE FALSE
END, `h.LastGameNavigation`.`gamestart`
FROM `HostConfigurations` AS `h`
LEFT JOIN `Games` AS `h.LastGameNavigation` ON `h`.`idGamesLast` = `h.LastGameNavigation`.`idGames`
LEFT JOIN `GameTypes` AS `h.LastGameNavigation.GameTypeNavigation` ON `h.LastGameNavigation`.`idGameTypes` = `h.LastGameNavigation.GameTypeNavigation`.`idGameTypes`

ERROR: Microsoft.EntityFrameworkCore.Query An exception occurred while iterating over the results of a query for context type '...'.
System.InvalidCastException: Unable to cast object of type 'System.String' to type 'System.DateTime'.
   at MySqlConnector.Core.Row.GetDateTime(Int32 ordinal) in C:\projects\mysqlconnector\src\MySqlConnector\Core\Row.cs:line 285
   at MySqlConnector.Core.Row.GetDateTimeOffset(Int32 ordinal) in C:\projects\mysqlconnector\src\MySqlConnector\Core\Row.cs:line 288
   at MySql.Data.MySqlClient.MySqlDataReader.GetFieldValue[T](Int32 ordinal) in C:\projects\mysqlconnector\src\MySqlConnector\MySql.Data.MySqlClient\MySqlDataReader.cs:line 261
   at lambda_method(Closure , DbDataReader )
   at Microsoft.EntityFrameworkCore.Storage.Internal.TypedRelationalValueBufferFactory.Create(DbDataReader dataReader)
   at Microsoft.EntityFrameworkCore.Query.Internal.AsyncQueryingEnumerable`1.AsyncEnumerator.BufferlessMoveNext(DbContext _, Boolean buffer, CancellationToken cancellationToken)
   at Pomelo.EntityFrameworkCore.MySql.Storage.Internal.MySqlExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func`4 operation, Func`4 verifySucceeded, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.Query.Internal.AsyncQueryingEnumerable`1.AsyncEnumerator.MoveNext(CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.Query.Internal.AsyncLinqOperatorProvider.ExceptionInterceptor`1.EnumeratorExceptionInterceptor.MoveNext(CancellationToken cancellationToken)

如果我从 lambda 方法中注释掉 'gameStart = ...' 行,则不会发生异常。显然,这是因为 MinValue 的日期时间文字在结果集中被解释为字符串。这似乎是 MySQL 连接器的严重限制?

非常感谢任何解决方法的想法!

【问题讨论】:

    标签: mysql entity-framework asp.net-core .net-core


    【解决方案1】:

    有一个解决方法。您可以将最小日期变量声明为DateTimeOffset? min = DateTimeOffset.MinValue 并在查询中使用它。

    context.HostConfigurations.Select (h => new HostStatus {
                id = h.IdHostConfigurations,
                hostname = h.Hostname,
                gameTitle = h.IdGamesLast.HasValue ? h.LastGameNavigation.GameTypeNavigation.Title : "-",
                gameStart = h.IdGamesLast.HasValue ? h.LastGameNavigation.Gamestart : min ,
                gameStartFriendly = h.IdGamesLast.HasValue ? h.LastGameNavigation.Gamestart.ToString ("ddd HH:mm") : "-"
            }).ToList ();
    

    【讨论】:

    • 很好,谢谢。因此,选择 DateTimeOffset 参数将生成具有正确 System.DateTime 类型的结果集。我自己也想不通。
    【解决方案2】:

    目前,我通过强制对表达式进行本地评估找到了解决连接器问题的方法:

            var hosts = await context.HostConfigurations.Include (h => h.LastGameNavigation).ThenInclude (lg => lg.GameTypeNavigation).ToListAsync ();
    
            var l = new List<HostStatus> ();
    
            hosts.ForEach (h => {
                l.Add (new HostStatus {
                    id = h.IdHostConfigurations,
                    hostname = h.Hostname,
                    gameTitle = h.IdGamesLast.HasValue ? h.LastGameNavigation.GameTypeNavigation.Title : "-",
                    gameStart = h.IdGamesLast.HasValue ? h.LastGameNavigation.Gamestart : DateTimeOffset.MinValue,
                    gameStartFriendly = h.IdGamesLast.HasValue ? h.LastGameNavigation.Gamestart.ToString ("ddd HH:mm") : "-",
                });
            });
    

    【讨论】:

      猜你喜欢
      • 2017-07-30
      • 2023-04-03
      • 1970-01-01
      • 1970-01-01
      • 2012-09-07
      • 2021-03-26
      • 2014-03-14
      • 2017-11-24
      • 1970-01-01
      相关资源
      最近更新 更多