创建具有时间跨度的模型
class MyModel {
TimeSpan t;
}
---
MyModel m() {t = TimeSpan.MaxValue};
db_context.Add(m);
await db_context.SaveChangesAsync()
TimeSpan 类型创建一个 TIME 类型的列,它的约束比 TimeSpan 小。 具体来说 TIME 只从'-838:59:59.000000' 到 '838:59:59.000000' 。 而 TimeSpan 可以达到 256204778:48:05.477580。
Unhandled exception. Microsoft.EntityFrameworkCore.DbUpdateException: An error occurred while updating the entries. See the inner exception for details.
---> MySql.Data.MySqlClient.MySqlException (0x80004005): Incorrect TIME value: '256204778:48:05.477580'
---> MySql.Data.MySqlClient.MySqlException (0x80004005): Incorrect TIME value: '256204778:48:05.477580'
at MySqlConnector.Core.ServerSession.ReceiveReplyAsyncAwaited(ValueTask`1 task) in C:\projects\mysqlconnector\src\MySqlConnector\Core\ServerSession.cs:line 774
at MySqlConnector.Core.ResultSet.ReadResultSetHeaderAsync(IOBehavior ioBehavior) in C:\projects\mysqlconnector\src\MySqlConnector\Core\ResultSet.cs:line 49
at MySql.Data.MySqlClient.MySqlDataReader.ActivateResultSet() in C:\projects\mysqlconnector\src\MySqlConnector\MySql.Data.MySqlClient\MySqlDataReader.cs:line 130
at MySql.Data.MySqlClient.MySqlDataReader.CreateAsync(CommandListPosition commandListPosition, ICommandPayloadCreator payloadCreator, IDictionary`2 cachedProcedures, IMySqlCommand command, CommandBehavior behavior, IOBehavior ioBehavior, CancellationToken cancellationToken) in C:\projects\mysqlconnector\src\MySqlConnector\MySql.Data.MySqlClient\MySqlDataReader.cs:line 391
at MySqlConnector.Core.CommandExecutor.ExecuteReaderAsync(IReadOnlyList`1 commands, ICommandPayloadCreator payloadCreator, CommandBehavior behavior, IOBehavior ioBehavior, CancellationToken cancellationToken) in C:\projects\mysqlconnector\src\MySqlConnector\Core\CommandExecutor.cs:line 62
at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.ExecuteAsync(IRelationalConnection connection, CancellationToken cancellationToken)
--- End of inner exception stack trace ---
at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.ExecuteAsync(IRelationalConnection connection, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.ExecuteAsync(IEnumerable`1 commandBatches, IRelationalConnection connection, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.ExecuteAsync(IEnumerable`1 commandBatches, IRelationalConnection connection, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(IList`1 entriesToSave, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(DbContext _, Boolean acceptAllChangesOnSuccess, 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.DbContext.SaveChangesAsync(Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken)
如果您需要超过一个月的时间跨度,请查看价值转换,特别是TimeSpanToStringConverter
和TimeSpanToTicksConverter
。
@mguinness谢谢你的提示。 我是否正确地将时间跨度转换器解释为被转换为刻度数,即数据库中的 Long 数?
此外,如果您无能为力,我将关闭错误报告。
TimeSpan 类型创建一个 TIME 类型的列,它的约束比 TimeSpan 小。 具体来说 TIME 只从 '-838:59:59.000000' 到 '838:59:59.000000' 。 而 TimeSpan 可以达到 256204778:48:05.477580。
这是意料之中的。 我们目前将TimeSpan
视为小于 24 小时的值。 所以即使new TimeSpan(1, 0, 0, 0)
也行不通。 这模仿了 SQL Server 的行为。
正如@mguinness指出的那样,使用TimeSpanToTicksConverter
是这里的方法。 它可以像这样使用:
```c#
entity.Property(e => e.BestServedBefore)
.HasColumnType("bigint")
.HasConversion(new TimeSpanToTicksConverter());
It is equivalent to the following code:
```c#
entity.Property(e => e.BestServedBefore)
.HasColumnType("bigint")
.HasConversion(v => v.Ticks, v => new TimeSpan(v));
这是一个功能齐全的示例:
```c#
使用系统;
使用 System.Diagnostics;
使用 System.Linq;
使用 Microsoft.EntityFrameworkCore;
使用 Microsoft.EntityFrameworkCore.Storage.ValueConversion;
使用 Microsoft.Extensions.Logging;
使用 Pomelo.EntityFrameworkCore.MySql.Infrastructure;
使用 Pomelo.EntityFrameworkCore.MySql.Storage;
命名空间 IssueConsoleTemplate
{
公开课冰淇淋
{
公共 int IceCreamId { 获取; 放; }
公共字符串名称 { 获取; 放; }
公共时间跨度 BestServedBefore { get; 放; }
}
public class Context : DbContext
{
public DbSet<IceCream> IceCreams { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder
.UseMySql(
"server=127.0.0.1;port=3306;user=root;password=;database=Issue1046",
b => b
.ServerVersion(new ServerVersion("8.0.20-mysql"))
.CharSetBehavior(CharSetBehavior.NeverAppend))
.UseLoggerFactory(
LoggerFactory.Create(
b => b
.AddConsole()
.AddFilter(level => level >= LogLevel.Information)))
.EnableSensitiveDataLogging()
.EnableDetailedErrors();
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<IceCream>(
entity =>
{
entity.Property(e => e.BestServedBefore)
.HasColumnType("bigint")
.HasConversion(new TimeSpanToTicksConverter());
entity.HasData(
new IceCream
{
IceCreamId = 1,
Name = "Vanilla",
BestServedBefore = new TimeSpan(0, 12, 0, 0)
},
new IceCream
{
IceCreamId = 2,
Name = "Chocolate",
BestServedBefore = new TimeSpan(0, 23, 59, 59)
},
new IceCream
{
IceCreamId = 3,
Name = "Artificial Vanilla",
// This will not work out-of-the box.
// Usage of a converter is necessary.
BestServedBefore = new TimeSpan(42, 11, 0, 0)
}
);
});
}
}
internal class Program
{
private static void Main()
{
using var context = new Context();
context.Database.EnsureDeleted();
context.Database.EnsureCreated();
var iceCreams = context.IceCreams
.OrderBy(i => i.IceCreamId)
.ToList();
Debug.Assert(iceCreams.Count == 3);
Debug.Assert(iceCreams[0].BestServedBefore == new TimeSpan(0, 12, 0, 0));
Debug.Assert(iceCreams[1].BestServedBefore == new TimeSpan(0, 23, 59, 59));
Debug.Assert(iceCreams[2].BestServedBefore == new TimeSpan(42, 11, 0, 0));
}
}
}
``