diff --git a/src/Thinktecture.Runtime.Extensions.EntityFrameworkCore.Sources/EntityFrameworkCore/Storage/ValueConversion/ValueObjectValueConverterFactory.cs b/src/Thinktecture.Runtime.Extensions.EntityFrameworkCore.Sources/EntityFrameworkCore/Storage/ValueConversion/ValueObjectValueConverterFactory.cs index b0b7c2fa..722fb9e6 100644 --- a/src/Thinktecture.Runtime.Extensions.EntityFrameworkCore.Sources/EntityFrameworkCore/Storage/ValueConversion/ValueObjectValueConverterFactory.cs +++ b/src/Thinktecture.Runtime.Extensions.EntityFrameworkCore.Sources/EntityFrameworkCore/Storage/ValueConversion/ValueObjectValueConverterFactory.cs @@ -96,6 +96,11 @@ private static Expression> GetConverterFromKey(bool useCo return (Expression>)(factoryMethod ?? throw new InvalidOperationException($"A value converter cannot be created for the type '{typeof(T).Name}' because it has no factory methods.")); } + private static T Convert(object value) + { + return (T)System.Convert.ChangeType(value, typeof(T)); + } + private sealed class ValueObjectValueConverter : ValueConverter where T : IValueObjectFactory, IValueObjectConvertable where TKey : notnull @@ -110,7 +115,8 @@ public ValueObjectValueConverter(bool useConstructor) { null => null, TKey key => key, // useful for comparisons of value objects with its key types - _ => ((T)o).ToValue() + T obj => obj.ToValue(), + _ => Convert(o) }; } } @@ -130,13 +136,15 @@ public ValidatableEnumValueConverter(bool validateOnWrite) { null => null, TKey key => key, // useful for comparisons of value objects with its key types - _ => GetKeyIfValid((TEnum)o) + TEnum obj => GetKeyIfValid(obj), + _ => Convert(o) } : o => o switch { null => null, TKey key => key, // useful for comparisons of value objects with its key types - _ => ((TEnum)o).ToValue() + TEnum obj => obj.ToValue(), + _ => Convert(o) }; } diff --git a/test/Thinktecture.Runtime.Extensions.EntityFrameworkCore.Tests.Sources/EntityFrameworkCore/ValueConversion/ValueObjectValueConverterFactoryTests.cs b/test/Thinktecture.Runtime.Extensions.EntityFrameworkCore.Tests.Sources/EntityFrameworkCore/ValueConversion/ValueObjectValueConverterFactoryTests.cs index 153f1383..ac620e84 100644 --- a/test/Thinktecture.Runtime.Extensions.EntityFrameworkCore.Tests.Sources/EntityFrameworkCore/ValueConversion/ValueObjectValueConverterFactoryTests.cs +++ b/test/Thinktecture.Runtime.Extensions.EntityFrameworkCore.Tests.Sources/EntityFrameworkCore/ValueConversion/ValueObjectValueConverterFactoryTests.cs @@ -83,9 +83,43 @@ UPDATE TestEntities_with_Enum_and_ValueObjects [Fact] public async Task Should_not_roundtrip_convert_underlying_type_to_value_object_and_back_to_underlying_type() { + var item = TestSmartEnum_Struct_IntBased.Value1; + TestSmartEnum_Struct_IntBased? nullableItem = item; + + var valueObj = IntBasedStructValueObject.Create(42); + IntBasedStructValueObject? nullableValueObj = valueObj; + + long int64 = 42; + long? nullableInt64 = int64; + int int32 = 42; + int? nullableInt32 = int32; + short int16 = 42; + short? nullableInt16 = int16; + decimal deci = 42; + decimal? nullableDecimal = deci; + await _ctx.TestEntities_with_Enum_and_ValueObjects - .Where(e => e.IntBasedStructValueObject == 42 - && e.TestSmartEnum_Struct_IntBased == 42) + .Where(e => e.TestSmartEnum_Struct_IntBased == item + && e.TestSmartEnum_Struct_IntBased == nullableItem + && e.IntBasedStructValueObject == valueObj + && e.IntBasedStructValueObject == nullableValueObj + && e.IntBasedStructValueObject == int64 + && e.TestSmartEnum_Struct_IntBased == int64 + && e.IntBasedStructValueObject == nullableInt64 + && e.TestSmartEnum_Struct_IntBased == nullableInt64 + && e.IntBasedStructValueObject == int32 + && e.TestSmartEnum_Struct_IntBased == int32 + && e.IntBasedStructValueObject == nullableInt32 + && e.TestSmartEnum_Struct_IntBased == nullableInt32 + && e.IntBasedStructValueObject == int16 + && e.TestSmartEnum_Struct_IntBased == int16 + && e.IntBasedStructValueObject == nullableInt16 + && e.TestSmartEnum_Struct_IntBased == nullableInt16 + && e.IntBasedStructValueObject == deci + && e.TestSmartEnum_Struct_IntBased == deci + && e.IntBasedStructValueObject == nullableDecimal + && e.TestSmartEnum_Struct_IntBased == nullableDecimal + ) .ToListAsync(); }