1111using System ;
1212using System . Data ;
1313using System . Data . Common ;
14-
1514using NHibernate . Engine ;
1615using NHibernate . Exceptions ;
1716using NHibernate . Impl ;
@@ -26,51 +25,34 @@ public partial class DbTimestampType : AbstractDateTimeType
2625 {
2726
2827 /// <inheritdoc />
29- public override Task < object > SeedAsync ( ISessionImplementor session , CancellationToken cancellationToken )
28+ public override async Task < object > SeedAsync ( ISessionImplementor session , CancellationToken cancellationToken )
3029 {
31- if ( cancellationToken . IsCancellationRequested )
32- {
33- return Task . FromCanceled < object > ( cancellationToken ) ;
34- }
35- try
30+ cancellationToken . ThrowIfCancellationRequested ( ) ;
31+ if ( session == null )
3632 {
37- if ( session == null )
38- {
39- log . Debug ( "incoming session was null; using current application host time" ) ;
40- return base . SeedAsync ( null , cancellationToken ) ;
41- }
42- if ( ! session . Factory . Dialect . SupportsCurrentTimestampSelection )
43- {
44- log . Info ( "falling back to application host based timestamp, as dialect does not support current timestamp selection" ) ;
45- return base . SeedAsync ( session , cancellationToken ) ;
46- }
47- return GetCurrentTimestampAsync ( session , cancellationToken ) ;
33+ log . Debug ( "incoming session was null; using current application host time" ) ;
34+ return await ( base . SeedAsync ( null , cancellationToken ) ) . ConfigureAwait ( false ) ;
4835 }
49- catch ( Exception ex )
36+ if ( ! session . Factory . Dialect . SupportsCurrentTimestampSelection )
5037 {
51- return Task . FromException < object > ( ex ) ;
38+ log . Info ( "falling back to application host based timestamp, as dialect does not support current timestamp selection" ) ;
39+ return await ( base . SeedAsync ( session , cancellationToken ) ) . ConfigureAwait ( false ) ;
5240 }
41+ return await ( GetCurrentTimestampAsync ( session , cancellationToken ) ) . ConfigureAwait ( false ) ;
5342 }
5443
55- private Task < object > GetCurrentTimestampAsync ( ISessionImplementor session , CancellationToken cancellationToken )
44+ protected virtual async Task < DateTime > GetCurrentTimestampAsync ( ISessionImplementor session , CancellationToken cancellationToken )
5645 {
57- if ( cancellationToken . IsCancellationRequested )
58- {
59- return Task . FromCanceled < object > ( cancellationToken ) ;
60- }
61- try
62- {
63- Dialect . Dialect dialect = session . Factory . Dialect ;
64- string timestampSelectString = dialect . CurrentTimestampSelectString ;
65- return UsePreparedStatementAsync ( timestampSelectString , session , cancellationToken ) ;
66- }
67- catch ( Exception ex )
68- {
69- return Task . FromException < object > ( ex ) ;
70- }
46+ cancellationToken . ThrowIfCancellationRequested ( ) ;
47+ var dialect = session . Factory . Dialect ;
48+ // Need to round notably for Sql Server DateTime with Odbc, which has a 3.33ms resolution,
49+ // causing stale data update failure 2/3 of times if not rounded to 10ms.
50+ return Round (
51+ await ( UsePreparedStatementAsync ( dialect . CurrentTimestampSelectString , session , cancellationToken ) ) . ConfigureAwait ( false ) ,
52+ dialect . TimestampResolutionInTicks ) ;
7153 }
7254
73- protected virtual async Task < object > UsePreparedStatementAsync ( string timestampSelectString , ISessionImplementor session , CancellationToken cancellationToken )
55+ protected virtual async Task < DateTime > UsePreparedStatementAsync ( string timestampSelectString , ISessionImplementor session , CancellationToken cancellationToken )
7456 {
7557 cancellationToken . ThrowIfCancellationRequested ( ) ;
7658 var tsSelect = new SqlString ( timestampSelectString ) ;
0 commit comments