Add option to configure the manner of mapping DateTimeOffset (#180)

* Add option to configure how to save/map a datetimeoffset i.e. as string or as a datetime
pull/182/head
Christopher Jolly 2 years ago committed by GitHub
parent 472f6b4665
commit ee8cfdb21f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -16,5 +16,13 @@ namespace EntityFrameworkCore.Jet.Infrastructure.Internal
bool UseOuterSelectSkipEmulationViaDataReader { get; }
bool EnableMillisecondsSupport { get; }
bool UseShortTextForSystemString { get; }
DateTimeOffsetType DateTimeOffsetType { get; }
}
public enum DateTimeOffsetType
{
SaveAsString = 0,
SaveAsDateTime = 1,
SaveAsDateTimeUtc = 2
}
}

@ -25,6 +25,7 @@ namespace EntityFrameworkCore.Jet.Infrastructure.Internal
private bool _useOuterSelectSkipEmulationViaDataReader;
private bool _enableMillisecondsSupport;
private bool _useShortTextForSystemString;
private DateTimeOffsetType _dateTimeOffsetType = DateTimeOffsetType.SaveAsString;
/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
@ -189,6 +190,23 @@ namespace EntityFrameworkCore.Jet.Infrastructure.Internal
return clone;
}
public virtual DateTimeOffsetType DateTimeOffsetType => _dateTimeOffsetType;
/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
public virtual JetOptionsExtension WithUseDateTimeOffsetType(DateTimeOffsetType dateTimeOffsetType = DateTimeOffsetType.SaveAsString)
{
var clone = (JetOptionsExtension)Clone();
clone._dateTimeOffsetType = dateTimeOffsetType;
return clone;
}
/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
@ -287,6 +305,8 @@ namespace EntityFrameworkCore.Jet.Infrastructure.Internal
= Extension._enableMillisecondsSupport.GetHashCode().ToString(CultureInfo.InvariantCulture);
debugInfo["Jet:" + nameof(JetDbContextOptionsBuilder.UseShortTextForSystemString)]
= Extension._useShortTextForSystemString.GetHashCode().ToString(CultureInfo.InvariantCulture);
debugInfo["Jet:" + nameof(JetDbContextOptionsBuilder.UseDateTimeOffsetType)]
= Extension._dateTimeOffsetType.GetHashCode().ToString(CultureInfo.InvariantCulture);
}
}
}

@ -66,6 +66,9 @@ namespace EntityFrameworkCore.Jet.Infrastructure
public virtual JetDbContextOptionsBuilder UseShortTextForSystemString(bool enabled = true)
=> WithOption(e => e.WithUseShortTextForSystemString(enabled));
public virtual JetDbContextOptionsBuilder UseDateTimeOffsetType(DateTimeOffsetType dateTimeOffsetType = DateTimeOffsetType.SaveAsString)
=> WithOption(e => e.WithUseDateTimeOffsetType(dateTimeOffsetType));
/// <summary>
/// Configures the context to use the default retrying <see cref="IExecutionStrategy" />.
/// </summary>

@ -31,6 +31,7 @@ namespace EntityFrameworkCore.Jet.Internal
EnableMillisecondsSupport = jetOptions.EnableMillisecondsSupport;
ConnectionString = jetOptions.Connection?.ConnectionString ?? jetOptions.ConnectionString!;
UseShortTextForSystemString = jetOptions.UseShortTextForSystemString;
DateTimeOffsetType = jetOptions.DateTimeOffsetType;
}
/// <summary>
@ -81,6 +82,13 @@ namespace EntityFrameworkCore.Jet.Internal
nameof(JetOptionsExtension.UseShortTextForSystemString),
nameof(DbContextOptionsBuilder.UseInternalServiceProvider)));
}
if (DateTimeOffsetType != jetOptions.DateTimeOffsetType)
{
throw new InvalidOperationException(
CoreStrings.SingletonOptionChanged(
nameof(JetOptionsExtension.DateTimeOffsetType),
nameof(DbContextOptionsBuilder.UseInternalServiceProvider)));
}
}
private static DataAccessProviderType GetDataAccessProviderTypeFromOptions(JetOptionsExtension jetOptions)
@ -159,5 +167,7 @@ namespace EntityFrameworkCore.Jet.Internal
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
public virtual string? ConnectionString { get; private set; }
public DateTimeOffsetType DateTimeOffsetType { get; private set; }
}
}

@ -2,6 +2,7 @@
using System;
using System.Data.Common;
using System.Globalization;
using EntityFrameworkCore.Jet.Infrastructure.Internal;
using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore.Storage;
@ -12,13 +13,12 @@ namespace EntityFrameworkCore.Jet.Storage.Internal
{
private readonly IJetOptions _options;
private const string DateTimeOffsetFormatConst = @"'{0:yyyy-MM-ddTHH:mm:ss.fffffffzzz}'";
private const string DateTimeFormatConst = @"'{0:yyyy-MM-dd HH:mm:ss}'";
public JetDateTimeOffsetTypeMapping(
[NotNull] string storeType,
[NotNull] IJetOptions options)
: base(
storeType, System.Data.DbType.String) // delibrately use DbType.DateTime, because OleDb will throw a
// "No mapping exists from DbType DateTimeOffset to a known OleDbType."
// exception when using DbType.DateTimeOffset.
storeType, options.DateTimeOffsetType == DateTimeOffsetType.SaveAsString ? System.Data.DbType.String : System.Data.DbType.DateTime)
{
_options = options;
}
@ -37,8 +37,21 @@ namespace EntityFrameworkCore.Jet.Storage.Internal
// OLE DB can't handle the DateTimeOffset type.
if (parameter.Value is DateTimeOffset dateTimeOffset)
{
parameter.Value = dateTimeOffset.ToString("O");
parameter.DbType = System.Data.DbType.String;
switch (_options.DateTimeOffsetType)
{
case DateTimeOffsetType.SaveAsString:
parameter.Value = dateTimeOffset.ToString("O");
parameter.DbType = System.Data.DbType.String;
break;
case DateTimeOffsetType.SaveAsDateTime:
parameter.Value = dateTimeOffset.DateTime;
parameter.DbType = System.Data.DbType.DateTime;
break;
case DateTimeOffsetType.SaveAsDateTimeUtc:
parameter.Value = dateTimeOffset.UtcDateTime;
parameter.DbType = System.Data.DbType.DateTime;
break;
}
}
base.ConfigureParameter(parameter);
@ -46,5 +59,27 @@ namespace EntityFrameworkCore.Jet.Storage.Internal
protected override string SqlLiteralFormatString
=> DateTimeOffsetFormatConst;
protected override string GenerateNonNullSqlLiteral(object value)
{
if (value is not DateTimeOffset offset) return base.GenerateNonNullSqlLiteral(value);
switch (_options.DateTimeOffsetType)
{
case DateTimeOffsetType.SaveAsString:
return base.GenerateNonNullSqlLiteral(offset);
case DateTimeOffsetType.SaveAsDateTime:
{
var dateTime = offset.DateTime;
return string.Format(CultureInfo.InvariantCulture, DateTimeFormatConst, dateTime);
}
case DateTimeOffsetType.SaveAsDateTimeUtc:
{
var dateTimeUtc = offset.DateTime;
return string.Format(CultureInfo.InvariantCulture, DateTimeFormatConst, dateTimeUtc);
}
default:
return "";
}
}
}
}

@ -92,7 +92,7 @@ namespace EntityFrameworkCore.Jet.Storage.Internal
_datetime = new JetDateTimeTypeMapping("datetime", options, dbType: DbType.DateTime);
_dateasdatetime = new JetDateTimeTypeMapping("date", options, dbType: DbType.Date);
_datetimeoffset = new JetDateTimeOffsetTypeMapping("varchar(50)", options);
_datetimeoffset = new JetDateTimeOffsetTypeMapping(options.DateTimeOffsetType == DateTimeOffsetType.SaveAsString ? "varchar(50)" : "datetime", options);
_dateonly = new JetDateOnlyTypeMapping("date", options, dbType: DbType.Date);
_timeonly = new JetTimeOnlyTypeMapping("time", options);
_timespan = new JetTimeSpanTypeMapping("datetime", options);

Loading…
Cancel
Save