我对数据库表有UNIQUE约束,在编写新记录时偶尔会抛出异常。约束包括三个字段 - 其中一个是DATETIMEOFFSET(7)
。当命中webapi
端点时,该字段的值被设置为当前时间。
我无法想到多个webapi请求会插入完全重复时间的任何原因 - 鉴于时间字段的准确性,这似乎不太可能。
不幸的是,我无法重现异常,我们偶尔会在日志中看到它。
我唯一能想到的是,如果在同一个请求中,实体框架在认为数据库写入失败后会以某种方式重试数据库写入,而不会导致异常。我们正在使用SqlAzureExecutionStrategy
,在对其ShouldRetryOn
方法进行反编译后,它看起来像是在重试以下错误代码...
40613:数据库目前无法使用 41301:发生事务依赖性故障,并且当前事务无法再提交。 41302:当前事务尝试更新自此事务启动以来已更新的记录。交易中止。 41305:由于可重复的读取验证失败,当前事务无法提交。 41325:由于可序列化验证失败,当前事务无法提交。 10928:资源ID:%d。数据库的%ls限制为%d且已达到。请参阅' http://go.microsoft.com/fwlink/?LinkId=267637'寻求帮助。 10929:资源ID:%d。 %ls最小保证是%d,最大限制是%d,数据库的当前使用率是%d。但是,服务器当前太忙,无法支持此数据库的%ls大于%d。见' http://go.microsoft.com/fwlink/?LinkId=26 40197:服务处理您的请求时遇到错误。请再试一次。错误代码%d。 40501:服务当前正忙。 10秒后重试请求。事件ID:%ls。代码:%d 233:列'%。* ls'在表格中'%。* ls'不能为空。 10053:由于符号不匹配或溢出以外的原因,无法转换数据值。 10054:一个或多个列的数据值溢出提供者使用的类型。 10060:连接错误 20:? 64:与服务器成功建立连接,但在登录前握手期间发生错误
我原本以为它只会在没有写入的情况下重试。是否有可能写入记录,但实体框架可能会感到困惑,无论如何都要再试一次?
以下是例外......
System.Data.Entity.Infrastructure.RetryLimitExceededException: Maximum number of retries (5) exceeded while executing database operations with 'MyExecutionStrategy'.
See inner exception for the most recent failure. ---> System.Data.Entity.Core.UpdateException: An error occurred while updating the entries.
See the inner exception for details. ---> System.Data.SqlClient.SqlException: Violation of UNIQUE KEY constraint 'UQ_SessionLog'. Cannot insert duplicate key in object 'dbo.SessionLog'. The duplicate key value is (f6aeb1b8-c747-4f0b-9053-bf95a5630662, 2016-07-12 11:42:32.7077612 01:00, 0).
The statement has been terminated.
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, TdsParserStateObject stateObj, Boolean%26 dataReady)
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%26 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%26 task, Boolean asyncWrite)
at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource`1 completion, String methodName, Boolean sendToPipe, Int32 timeout, Boolean asyncWrite)
at System.Data.SqlClient.SqlCommand.ExecuteNonQuery()
at StackExchange.Profiling.Data.ProfiledDbCommand.ExecuteNonQuery() in d:\Files\GitHub\miniprofiler\dotnet\StackExchange.Profiling\Data\ProfiledDbCommand.cs:line 264
at System.Data.Common.DbCommand.ExecuteNonQueryAsync(CancellationToken cancellationToken)
答案 0 :(得分:4)
DateTime的精度不会超过毫秒数字会让您相信的数字。您很可能会在多线程环境中获得重复
试图找到一个权威的答案,确切地说它是多么精确: https://msdn.microsoft.com/EN-US/library/system.datetime.utcnow.aspx
"此属性的分辨率取决于系统计时器。"
您不是第一个遇到此问题的人
DateTime precision vs accuracy?
https://manski.net/2014/07/high-resolution-clock-in-csharp/
等等