使用 ServiceStack OrmLite 和 C# 将 TimeSpan 作为时间列保存到 SQL Server 2012
Saving TimeSpan into SQL Server 2012 as a Time column with ServiceStack OrmLite and C#
我在数据库 table 中有一个 Time(7)
列,我想使用 C# 和 ORMLite 作为对象关系映射器保存一个 TimeSpan
。执行此操作时我得到此异常
Operand type clash: bigint is incompatible with time
这是我的服务器堆栈跟踪;
[UpdateJobFrequency: 11/07/2015 5:43:39 AM]:
[REQUEST: {JobFrequency:{Id:0,JobId:3,FrequencyId:2,InstanceOfFrequency:1,Time:PT1H,WeekNumber:0}}]
System.Data.SqlClient.SqlException (0x80131904): Operand type clash: bigint is incompatible with time
at System.Data.SqlClient.SqlConnection.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, TdsParserStateObject stateObj, Boolean& dataReady)
at System.Data.SqlClient.SqlDataReader.TryConsumeMetaData()
at System.Data.SqlClient.SqlDataReader.get_MetaData()
at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString)
at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async, Int32 timeout, Task& task, Boolean asyncWrite, SqlDataReader ds)
at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, TaskCompletionSource`1 completion, Int32 timeout, Task& task, Boolean asyncWrite)
at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method)
at System.Data.SqlClient.SqlCommand.ExecuteScalar()
at ServiceStack.OrmLite.OrmLiteCommand.ExecuteScalar()
at ServiceStack.OrmLite.OrmLiteReadCommandExtensions.LongScalar(IDbCommand dbCmd)
at ServiceStack.OrmLite.OrmLiteResultsFilterExtensions.ExecLongScalar(IDbCommand dbCmd, String sql)
at ServiceStack.OrmLite.OrmLiteDialectProviderBase`1.InsertAndGetLastInsertId[T](IDbCommand dbCmd)
at ServiceStack.OrmLite.OrmLiteWriteCommandExtensions.Insert[T](IDbCommand dbCmd, T obj, Boolean selectIdentity)
at ServiceStack.OrmLite.OrmLiteWriteApi.<>c__DisplayClass4`1.<Insert>b__3(IDbCommand dbCmd)
at ServiceStack.OrmLite.OrmLiteExecFilter.Exec[T](IDbConnection dbConn, Func`2 filter)
at ServiceStack.OrmLite.OrmLiteReadExpressionsApi.Exec[T](IDbConnection dbConn, Func`2 filter)
at ServiceStack.OrmLite.OrmLiteWriteApi.Insert[T](IDbConnection dbConn, T obj, Boolean selectIdentity)
at JobRepositoryBase.<Create>d__a`1.MoveNext() in c:\dev\RepositoryBase.cs:line 89
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at Job.WebAppHost.Service.JobFrequencyService.<Post>d__6.MoveNext() in c:\dev\JobFrequencyService.cs:line 30
我从界面将 01:00:00
作为 TimeSpan
值传递,但它在服务器端的对象中显示为 Time: PT1H
。
此外,我在一份堆栈溢出问卷中读到 ADO.Net TimeSpan
映射到 SQL 服务器 Time(7)
。而且我相信 servicestack ORMLite 是建立在 ADO.Net 之上的。但是,在这种情况下,我遇到了这个例外。
如有任何帮助,我们将不胜感激。
由于紧急,我不得不为这个问题做一个解决方法,我不得不将我的 table 的数据类型更改为 BigInt。所以,ORMLite 正在做的是将 BigInt 映射为 TimeSpan,反之亦然 - Github,现在我可以毫无问题地存储和检索该字段。
但我仍然认为这不是一个完美的解决方案,因为在我的情况下,我是从头开发数据库,但在有人必须使用现有数据库的情况下,此解决方法会失败。
为了将来参考,现在有一个有效的解决方案,可以将 MS SQL 的 'Time' 列与 ORMLite 一起使用,映射到 C# 中的 TimeSpan 类型。只需将下面的代码放在您的 C# 应用程序中的任意位置:
//Enable ORMLite to suppot MS SQL 'Time' column
//Based on https://github.com/ServiceStack/ServiceStack.OrmLite/wiki/OrmLite-Type-Converters
SqlServerDialect.Provider.RegisterConverter<TimeSpan>(new ServiceStack.OrmLite.SqlServer.Converters.SqlServerTimeConverter
{
Precision = 7
});
我在数据库 table 中有一个 Time(7)
列,我想使用 C# 和 ORMLite 作为对象关系映射器保存一个 TimeSpan
。执行此操作时我得到此异常
Operand type clash: bigint is incompatible with time
这是我的服务器堆栈跟踪;
[UpdateJobFrequency: 11/07/2015 5:43:39 AM]:
[REQUEST: {JobFrequency:{Id:0,JobId:3,FrequencyId:2,InstanceOfFrequency:1,Time:PT1H,WeekNumber:0}}]
System.Data.SqlClient.SqlException (0x80131904): Operand type clash: bigint is incompatible with time
at System.Data.SqlClient.SqlConnection.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, TdsParserStateObject stateObj, Boolean& dataReady)
at System.Data.SqlClient.SqlDataReader.TryConsumeMetaData()
at System.Data.SqlClient.SqlDataReader.get_MetaData()
at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString)
at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async, Int32 timeout, Task& task, Boolean asyncWrite, SqlDataReader ds)
at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, TaskCompletionSource`1 completion, Int32 timeout, Task& task, Boolean asyncWrite)
at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method)
at System.Data.SqlClient.SqlCommand.ExecuteScalar()
at ServiceStack.OrmLite.OrmLiteCommand.ExecuteScalar()
at ServiceStack.OrmLite.OrmLiteReadCommandExtensions.LongScalar(IDbCommand dbCmd)
at ServiceStack.OrmLite.OrmLiteResultsFilterExtensions.ExecLongScalar(IDbCommand dbCmd, String sql)
at ServiceStack.OrmLite.OrmLiteDialectProviderBase`1.InsertAndGetLastInsertId[T](IDbCommand dbCmd)
at ServiceStack.OrmLite.OrmLiteWriteCommandExtensions.Insert[T](IDbCommand dbCmd, T obj, Boolean selectIdentity)
at ServiceStack.OrmLite.OrmLiteWriteApi.<>c__DisplayClass4`1.<Insert>b__3(IDbCommand dbCmd)
at ServiceStack.OrmLite.OrmLiteExecFilter.Exec[T](IDbConnection dbConn, Func`2 filter)
at ServiceStack.OrmLite.OrmLiteReadExpressionsApi.Exec[T](IDbConnection dbConn, Func`2 filter)
at ServiceStack.OrmLite.OrmLiteWriteApi.Insert[T](IDbConnection dbConn, T obj, Boolean selectIdentity)
at JobRepositoryBase.<Create>d__a`1.MoveNext() in c:\dev\RepositoryBase.cs:line 89
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at Job.WebAppHost.Service.JobFrequencyService.<Post>d__6.MoveNext() in c:\dev\JobFrequencyService.cs:line 30
我从界面将 01:00:00
作为 TimeSpan
值传递,但它在服务器端的对象中显示为 Time: PT1H
。
此外,我在一份堆栈溢出问卷中读到 ADO.Net TimeSpan
映射到 SQL 服务器 Time(7)
。而且我相信 servicestack ORMLite 是建立在 ADO.Net 之上的。但是,在这种情况下,我遇到了这个例外。
如有任何帮助,我们将不胜感激。
由于紧急,我不得不为这个问题做一个解决方法,我不得不将我的 table 的数据类型更改为 BigInt。所以,ORMLite 正在做的是将 BigInt 映射为 TimeSpan,反之亦然 - Github,现在我可以毫无问题地存储和检索该字段。
但我仍然认为这不是一个完美的解决方案,因为在我的情况下,我是从头开发数据库,但在有人必须使用现有数据库的情况下,此解决方法会失败。
为了将来参考,现在有一个有效的解决方案,可以将 MS SQL 的 'Time' 列与 ORMLite 一起使用,映射到 C# 中的 TimeSpan 类型。只需将下面的代码放在您的 C# 应用程序中的任意位置:
//Enable ORMLite to suppot MS SQL 'Time' column
//Based on https://github.com/ServiceStack/ServiceStack.OrmLite/wiki/OrmLite-Type-Converters
SqlServerDialect.Provider.RegisterConverter<TimeSpan>(new ServiceStack.OrmLite.SqlServer.Converters.SqlServerTimeConverter
{
Precision = 7
});