diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs index c82912f0f1..9a61e7f8e3 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.ComponentModel; using System.ComponentModel.DataAnnotations.Schema; using System.Globalization; using System.Linq; @@ -22,6 +23,7 @@ using Volo.Abp.EntityFrameworkCore.EntityHistory; using Volo.Abp.EntityFrameworkCore.Modeling; using Volo.Abp.EntityFrameworkCore.ValueConverters; using Volo.Abp.Guids; +using Volo.Abp.Localization; using Volo.Abp.MultiTenancy; using Volo.Abp.ObjectExtending; using Volo.Abp.Reflection; @@ -339,7 +341,20 @@ namespace Volo.Abp.EntityFrameworkCore { if (TypeHelper.IsPrimitiveExtended(entryProperty.Metadata.ClrType, includeEnums: true)) { - entryProperty.CurrentValue = Convert.ChangeType(entityProperty, entryProperty.Metadata.ClrType, CultureInfo.InvariantCulture); + var conversionType = entryProperty.Metadata.ClrType; + if (TypeHelper.IsNullable(conversionType)) + { + conversionType = conversionType.GetFirstGenericArgumentIfNullable(); + } + + if (conversionType == typeof(Guid)) + { + entryProperty.CurrentValue = TypeDescriptor.GetConverter(conversionType).ConvertFromInvariantString(entityProperty.ToString()); + } + else + { + entryProperty.CurrentValue = Convert.ChangeType(entityProperty, conversionType, CultureInfo.InvariantCulture); + } } } } diff --git a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/Data/HasExtraPropertiesExtensions.cs b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/Data/HasExtraPropertiesExtensions.cs index 6abb350328..22b135c3d0 100644 --- a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/Data/HasExtraPropertiesExtensions.cs +++ b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/Data/HasExtraPropertiesExtensions.cs @@ -1,7 +1,9 @@ using System; using System.Collections.Generic; +using System.ComponentModel; using System.Globalization; using Volo.Abp.DynamicProxy; +using Volo.Abp.Localization; using Volo.Abp.ObjectExtending; using Volo.Abp.Reflection; @@ -32,15 +34,26 @@ namespace Volo.Abp.Data if (TypeHelper.IsPrimitiveExtended(typeof(TProperty), includeEnums: true)) { - return (TProperty)Convert.ChangeType(value, typeof(TProperty), CultureInfo.InvariantCulture); + var conversionType = typeof(TProperty); + if (TypeHelper.IsNullable(conversionType)) + { + conversionType = conversionType.GetFirstGenericArgumentIfNullable(); + } + + if (conversionType == typeof(Guid)) + { + return (TProperty)TypeDescriptor.GetConverter(conversionType).ConvertFromInvariantString(value.ToString()); + } + + return (TProperty)Convert.ChangeType(value, conversionType, CultureInfo.InvariantCulture); } throw new AbpException("GetProperty does not support non-primitive types. Use non-generic GetProperty method and handle type casting manually."); } public static TSource SetProperty( - this TSource source, - string name, + this TSource source, + string name, object value, bool validate = true) where TSource : IHasExtraProperties @@ -96,4 +109,4 @@ namespace Volo.Abp.Data ((IHasExtraProperties) source).SetDefaultsForExtraProperties(objectType); } } -} \ No newline at end of file +} diff --git a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/Domain/ExtraProperties_Tests.cs b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/Domain/ExtraProperties_Tests.cs index f8edd1f5f1..f94f16c390 100644 --- a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/Domain/ExtraProperties_Tests.cs +++ b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/Domain/ExtraProperties_Tests.cs @@ -29,15 +29,18 @@ namespace Volo.Abp.EntityFrameworkCore.Domain london.ExtraProperties["PhoneCode"] = 123456; london.ExtraProperties["Rank"] = "88"; london.ExtraProperties["ZipCode"] = null; + london.ExtraProperties["Established"] = DateTime.MinValue; + london.ExtraProperties["Guid"] = "a7ae2efe-d8d6-466b-92e3-da14aa6e1c5b"; await CityRepository.UpdateAsync(london); var london2 = await CityRepository.FindByNameAsync("London"); london2.GetProperty("PhoneCode").ShouldBe("123456"); london2.GetProperty("Rank").ShouldBe(88); london2.GetProperty("ZipCode").ShouldBe(null); + london2.GetProperty("Established").ShouldBe(DateTime.MinValue); + london2.GetProperty("Guid").ShouldBe(new Guid("a7ae2efe-d8d6-466b-92e3-da14aa6e1c5b")); } - [Fact] public async Task An_Extra_Property_Configured_As_Extension2() { diff --git a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/Domain/TestEntityExtensionConfigurator.cs b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/Domain/TestEntityExtensionConfigurator.cs index dd723ffb55..15868e3966 100644 --- a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/Domain/TestEntityExtensionConfigurator.cs +++ b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/Domain/TestEntityExtensionConfigurator.cs @@ -1,4 +1,5 @@ -using Volo.Abp.ObjectExtending; +using System; +using Volo.Abp.ObjectExtending; using Volo.Abp.TestApp.Domain; using Volo.Abp.Threading; @@ -24,6 +25,10 @@ namespace Volo.Abp.EntityFrameworkCore.Domain "ZipCode" ).MapEfCoreProperty( "Rank" + ).MapEfCoreProperty( + "Established" + ).MapEfCoreProperty( + "Guid" ); }); } diff --git a/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/TestDataBuilder.cs b/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/TestDataBuilder.cs index 4b5f390d85..36874abad1 100644 --- a/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/TestDataBuilder.cs +++ b/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/TestDataBuilder.cs @@ -52,7 +52,8 @@ namespace Volo.Abp.TestApp { { "Population", 10_470_000 }, { "PhoneCode", "42" }, - { "ZipCode", "1000" } + { "ZipCode", "1000" }, + { "Guid", "a5ed8170-30b9-4580-a395-a3c2dbc031ee" } } }); await _cityRepository.InsertAsync(istanbul); diff --git a/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/HasExtraPropertiesExtensions_Tests.cs b/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/HasExtraPropertiesExtensions_Tests.cs index 918e96581b..633c0a0257 100644 --- a/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/HasExtraPropertiesExtensions_Tests.cs +++ b/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/HasExtraPropertiesExtensions_Tests.cs @@ -32,6 +32,18 @@ namespace Volo.Abp.TestApp.Testing city.HasProperty("IsHot").ShouldBeFalse(); city.GetProperty("IsHot").ShouldBeFalse(); city.GetProperty("IsHot", true).ShouldBeTrue(); + + city.GetProperty("IsHot?").ShouldBeNull(); + city.GetProperty("IsHot?", true).Value.ShouldBeTrue(); + + city.SetProperty("Guid", "2260AFEC-BBFD-42D4-A91A-DCB11E09B17F"); + city.GetProperty("Guid").ShouldBe(new Guid("2260AFEC-BBFD-42D4-A91A-DCB11E09B17F")); + + city.SetProperty("Guid?", "2260AFEC-BBFD-42D4-A91A-DCB11E09B17F"); + city.GetProperty("Guid?").ShouldBe(new Guid("2260AFEC-BBFD-42D4-A91A-DCB11E09B17F")); + + city.SetProperty("DateTime?", DateTime.MinValue); + city.GetProperty("DateTime?").ShouldBe(DateTime.MinValue); } } -} \ No newline at end of file +}