[SOLVED] ASP.NET Storing TimeSpan in EF Database

Issue

I am trying to store timespan objects in a EF Sql Database as:

public class Test
{
  [Required, Key]
  public int TestId { get; set; }
  public TimeSpan Time { get; set; }
}

modelBuilder.Entity<Test>().HasData(
                new Test {TestId = 1, Time = TimeSpan.FromDays(5)}
)

But I get the error:

System.Data.SqlClient.SqlException (0x80131904): Conversion failed when converting date and/or time from character string.
   at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
   at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
   at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
   at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserState
Object stateObj, Boolean& dataReady)
   at System.Data.SqlClient.SqlCommand.RunExecuteNonQueryTds(String methodName, Boolean async, Int32 timeout, Boolean asyncWrite)
   at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource`1 completion, Boolean sendToPipe, Int32 timeout, Boolean asyncWrite, String methodName)
   at System.Data.SqlClient.SqlCommand.ExecuteNonQuery()
   at Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommand.Execute(IRelationalConnection connection, DbCommandMethod executeMethod, IReadOnlyDictionary`2 paramete
rValues)
   at Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommand.ExecuteNonQuery(IRelationalConnection connection, IReadOnlyDictionary`2 parameterValues)
   at Microsoft.EntityFrameworkCore.Migrations.MigrationCommand.ExecuteNonQuery(IRelationalConnection connection, IReadOnlyDictionary`2 parameterValues)
   at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationCommandExecutor.ExecuteNonQuery(IEnumerable`1 migrationCommands, IRelationalConnection connection)
   at Microsoft.EntityFrameworkCore.Migrations.Internal.Migrator.Migrate(String targetMigration)
   at Microsoft.EntityFrameworkCore.Design.Internal.MigrationsOperations.UpdateDatabase(String targetMigration, String contextType)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.UpdateDatabase.<>c__DisplayClass0_1.<.ctor>b__0()
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)
ClientConnectionId:b2ff74ea-6a41-49c5-9e24-fefe36619f40
Error Number:241,State:1,Class:16
Conversion failed when converting date and/or time from character string.

How can I store them in a format SQL is happy with?

Solution

If you are using .net core 2.1 or newer you can use Value Conversion to Ticks like so :

builder.Entity<Test>()
    .Property(s => s.Time)
    .HasConversion(new TimeSpanToTicksConverter());

If you running older versions you have to do this manually by having a property of type Long that records the ticks into database and a not mapped property that match your span like so :

public class Test
{
  [Required, Key]
  public int TestId { get; set; }
  public long TimeTicks { get { return Time.Ticks; } set { Time = TimeSpan.FromTicks( value );}}
  [NotMapped]
  public TimeSpan Time { get; set; }
}

Answered By – Tiago Silva

Answer Checked By – Senaida (BugsFixing Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *