From 580aecba007959b92ed00daf434dfc4b86d8e0f6 Mon Sep 17 00:00:00 2001 From: Dmitrii Kiselev Date: Fri, 27 Sep 2024 17:21:40 +0500 Subject: [PATCH] feat(data-reader): add support for converting `DateOnly` and `TimeOnly` types from string This commit adds missing support for converting `DateOnly` and `TimeOnly` types from string. --- .../EFTableRowsDataReader.cs | 10 +++ .../EFTableRowsDataReaderTests.cs | 66 +++++++++++++++++-- 2 files changed, 70 insertions(+), 6 deletions(-) diff --git a/src/EFCoreSecondLevelCacheInterceptor/EFTableRowsDataReader.cs b/src/EFCoreSecondLevelCacheInterceptor/EFTableRowsDataReader.cs index de91449..5bc8b77 100644 --- a/src/EFCoreSecondLevelCacheInterceptor/EFTableRowsDataReader.cs +++ b/src/EFCoreSecondLevelCacheInterceptor/EFTableRowsDataReader.cs @@ -579,11 +579,21 @@ public override T GetFieldValue(int ordinal) return (T)(object)DateOnly.FromDateTime((DateTime)value); } + if (expectedValueType == TypeExtensions.DateOnlyType && actualValueType == TypeExtensions.StringType) + { + return (T)(object)DateOnly.Parse((string)value, CultureInfo.InvariantCulture); + } + if (expectedValueType == TypeExtensions.TimeOnlyType && actualValueType == TypeExtensions.TimeSpanType) { return (T)(object)TimeOnly.FromTimeSpan((TimeSpan)value); } + if (expectedValueType == TypeExtensions.TimeOnlyType && actualValueType == TypeExtensions.StringType) + { + return (T)(object)TimeOnly.Parse((string)value, CultureInfo.InvariantCulture); + } + if (expectedValueType == TypeExtensions.TimeOnlyType && isActualValueTypeNumber) { return (T)(object)TimeOnly.FromTimeSpan(new TimeSpan(Convert.ToInt64(value, CultureInfo.InvariantCulture))); diff --git a/src/Tests/EFCoreSecondLevelCacheInterceptor.UnitTests/EFTableRowsDataReaderTests.cs b/src/Tests/EFCoreSecondLevelCacheInterceptor.UnitTests/EFTableRowsDataReaderTests.cs index 0b69f61..c1952e8 100644 --- a/src/Tests/EFCoreSecondLevelCacheInterceptor.UnitTests/EFTableRowsDataReaderTests.cs +++ b/src/Tests/EFCoreSecondLevelCacheInterceptor.UnitTests/EFTableRowsDataReaderTests.cs @@ -1567,7 +1567,7 @@ public void GetFieldValue_ShouldReturnExpectedDateOnlyValueFromDateTime() } [Fact] - public void GetFieldValue__ShouldReturnExpectedDateTimeOffsetValueFromString() + public void GetFieldValue_ShouldReturnExpectedDateOnlyValueFromString() { // Arrange var values = new List { DateOnly.MaxValue.ToString(CultureInfo.InvariantCulture) }; @@ -1580,15 +1580,42 @@ public void GetFieldValue__ShouldReturnExpectedDateTimeOffsetValueFromString() { 0, new EFTableColumnInfo { DbTypeName = nameof(String), Ordinal = 0 } } } }; + var dataReader = new EFTableRowsDataReader(tableRows); dataReader.Read(); // Act - void Act() => dataReader.GetFieldValue(0); + var actual = dataReader.GetFieldValue(0); // Assert - Assert.Throws(Act); + Assert.Equal(DateOnly.MaxValue, actual); + } + + [Fact] + public void GetFieldValue_ShouldNotThrowInvalidCastExceptionWhenValueConversionFromStringToDateOnly() + { + // Arrange + var values = new List { DateOnly.MaxValue.ToString(CultureInfo.InvariantCulture) }; + var tableRow = new EFTableRow(values); + var tableRows = new EFTableRows + { + Rows = new List { tableRow }, + ColumnsInfo = new Dictionary + { + { 0, new EFTableColumnInfo { DbTypeName = nameof(String), Ordinal = 0 } } + } + }; + + var dataReader = new EFTableRowsDataReader(tableRows); + + dataReader.Read(); + + // Act + var exception = Record.Exception(() => dataReader.GetFieldValue(0)); + + // Assert + Assert.Null(exception); } [Fact] @@ -1643,6 +1670,32 @@ public void GetFieldValue_ShouldReturnExpectedTimeOnlyValueFromNumber() [Fact] public void GetFieldValue_ShouldReturnExpectedTimeOnlyValueFromString() + { + // Arrange + var values = new List { TimeOnly.MaxValue.ToString("O", CultureInfo.InvariantCulture) }; + var tableRow = new EFTableRow(values); + var tableRows = new EFTableRows + { + Rows = new List { tableRow }, + ColumnsInfo = new Dictionary + { + { 0, new EFTableColumnInfo { DbTypeName = nameof(String), Ordinal = 0 } } + } + }; + + var dataReader = new EFTableRowsDataReader(tableRows); + + dataReader.Read(); + + // Act + var actual = dataReader.GetFieldValue(0); + + // Assert + Assert.Equal(TimeOnly.MaxValue, actual); + } + + [Fact] + public void GetFieldValue_ShouldNotThrowInvalidCastExceptionWhenValueConversionFromStringToTimeOnly() { // Arrange var values = new List { TimeOnly.MaxValue.ToString(CultureInfo.InvariantCulture) }; @@ -1652,18 +1705,19 @@ public void GetFieldValue_ShouldReturnExpectedTimeOnlyValueFromString() Rows = new List { tableRow }, ColumnsInfo = new Dictionary { - { 0, new EFTableColumnInfo { DbTypeName = nameof(TimeSpan), Ordinal = 0 } } + { 0, new EFTableColumnInfo { DbTypeName = nameof(String), Ordinal = 0 } } } }; + var dataReader = new EFTableRowsDataReader(tableRows); dataReader.Read(); // Act - void Act() => dataReader.GetFieldValue(0); + var exception = Record.Exception(() => dataReader.GetFieldValue(0)); // Assert - Assert.Throws(Act); + Assert.Null(exception); } [Fact]