Browse Source

Added DataTimeValueConverters function.

Resolve #1983
pull/2000/head
maliming 7 years ago
parent
commit
4eadee29c6
  1. 43
      framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs
  2. 17
      framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ValueConverters/AbpDateTimeValueConverter.cs
  3. 9
      framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/ValueConverters/AbpDateTimeValueConverter_Tests.cs
  4. 6
      framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Domain/Person.cs
  5. 53
      framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/AbpDateTimeValueConverter_Tests.cs

43
framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs

@ -18,10 +18,12 @@ using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Entities;
using Volo.Abp.Domain.Entities.Events;
using Volo.Abp.EntityFrameworkCore.EntityHistory;
using Volo.Abp.EntityFrameworkCore.ValueConverters;
using Volo.Abp.Guids;
using Volo.Abp.MultiTenancy;
using Volo.Abp.Reflection;
using Volo.Abp.Threading;
using Volo.Abp.Timing;
namespace Volo.Abp.EntityFrameworkCore
{
@ -48,6 +50,8 @@ namespace Volo.Abp.EntityFrameworkCore
public IAuditingManager AuditingManager { get; set; }
public IClock Clock { get; set; }
public ILogger<AbpDbContext<TDbContext>> Logger { get; set; }
private static readonly MethodInfo ConfigureBasePropertiesMethodInfo
@ -57,6 +61,13 @@ namespace Volo.Abp.EntityFrameworkCore
BindingFlags.Instance | BindingFlags.NonPublic
);
private static readonly MethodInfo ConfigureValueConverterMethodInfo
= typeof(AbpDbContext<TDbContext>)
.GetMethod(
nameof(ConfigureValueConverter),
BindingFlags.Instance | BindingFlags.NonPublic
);
protected AbpDbContext(DbContextOptions<TDbContext> options)
: base(options)
{
@ -75,6 +86,10 @@ namespace Volo.Abp.EntityFrameworkCore
ConfigureBasePropertiesMethodInfo
.MakeGenericMethod(entityType.ClrType)
.Invoke(this, new object[] { modelBuilder, entityType });
ConfigureValueConverterMethodInfo
.MakeGenericMethod(entityType.ClrType)
.Invoke(this, new object[] { modelBuilder, entityType });
}
}
@ -488,6 +503,34 @@ namespace Volo.Abp.EntityFrameworkCore
}
}
protected virtual void ConfigureValueConverter<TEntity>(ModelBuilder modelBuilder, IMutableEntityType mutableEntityType)
where TEntity : class
{
if (mutableEntityType.BaseType == null &&
!typeof(TEntity).IsDefined(typeof(DisableDateTimeNormalizationAttribute), true) &&
!typeof(TEntity).IsDefined(typeof(OwnedAttribute), true) &&
!mutableEntityType.IsOwned())
{
var dateTimeValueConverter = new AbpDateTimeValueConverter(Clock);
var dateTimePropertyInfos = typeof(TEntity).GetProperties()
.Where(property =>
(property.PropertyType == typeof(DateTime) ||
property.PropertyType == typeof(DateTime?)) &&
property.CanWrite &&
!property.IsDefined(typeof(DisableDateTimeNormalizationAttribute), true)
).ToList();
dateTimePropertyInfos.ForEach(property =>
{
modelBuilder
.Entity<TEntity>()
.Property(property.Name)
.HasConversion(dateTimeValueConverter);
});
}
}
protected virtual bool ShouldFilterEntity<TEntity>(IMutableEntityType entityType) where TEntity : class
{
if (typeof(IMultiTenant).IsAssignableFrom(typeof(TEntity)))

17
framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ValueConverters/AbpDateTimeValueConverter.cs

@ -0,0 +1,17 @@
using System;
using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Volo.Abp.Timing;
namespace Volo.Abp.EntityFrameworkCore.ValueConverters
{
public class AbpDateTimeValueConverter : ValueConverter<DateTime?, DateTime?>
{
public AbpDateTimeValueConverter(IClock clock, [CanBeNull] ConverterMappingHints mappingHints = null)
: base(
x => x.HasValue ? clock.Normalize(x.Value) : x,
x => x.HasValue ? clock.Normalize(x.Value) : x, mappingHints)
{
}
}
}

9
framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/ValueConverters/AbpDateTimeValueConverter_Tests.cs

@ -0,0 +1,9 @@
using Volo.Abp.TestApp.Testing;
namespace Volo.Abp.EntityFrameworkCore.ValueConverters
{
public class AbpDateTimeValueConverter_Tests : AbpDateTimeValueConverter_Tests<AbpEntityFrameworkCoreTestModule>
{
}
}

6
framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Domain/Person.cs

@ -2,6 +2,7 @@ using System;
using System.Collections.ObjectModel;
using Volo.Abp.Domain.Entities.Auditing;
using Volo.Abp.MultiTenancy;
using Volo.Abp.Timing;
namespace Volo.Abp.TestApp.Domain
{
@ -15,6 +16,11 @@ namespace Volo.Abp.TestApp.Domain
public virtual int Age { get; set; }
public virtual DateTime? Birthday { get; set; }
[DisableDateTimeNormalization]
public virtual DateTime? LastActive { get; set; }
public virtual Collection<Phone> Phones { get; set; }
private Person()

53
framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/AbpDateTimeValueConverter_Tests.cs

@ -0,0 +1,53 @@
using System;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Shouldly;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Modularity;
using Volo.Abp.TestApp.Domain;
using Volo.Abp.Timing;
using Xunit;
namespace Volo.Abp.TestApp.Testing
{
public abstract class AbpDateTimeValueConverter_Tests<TStartupModule> : TestAppTestBase<TStartupModule>
where TStartupModule : IAbpModule
{
private readonly IBasicRepository<Person, Guid> _personRepository;
protected AbpDateTimeValueConverter_Tests()
{
_personRepository = GetRequiredService<IBasicRepository<Person, Guid>>();
}
protected override void AfterAddApplication(IServiceCollection services)
{
services.Configure<AbpClockOptions>(options => options.Kind = DateTimeKind.Utc);
}
[Fact]
public async Task DateTime_Kind_Should_Be_Normalized_To_UTC_Test()
{
var personId = Guid.Parse("4125582e-d100-4c27-aa84-e4de85830dca");
await _personRepository.InsertAsync(new Person(personId, "bob lee", 18)
{
Birthday = DateTime.Parse("2020-01-01 00:00:00"),
LastActive = DateTime.Parse("2020-01-01 00:00:00"),
}, true);
var person = await _personRepository.GetAsync(personId);
person.ShouldNotBeNull();
person.CreationTime.Kind.ShouldBe(DateTimeKind.Utc);
person.Birthday.ShouldNotBeNull();
person.Birthday.Value.Kind.ShouldBe(DateTimeKind.Utc);
person.Birthday.Value.ToString("yyy-MM-dd HH:mm:ss").ShouldBe("2020-01-01 00:00:00");
//LastActive DisableDateTimeNormalization
person.LastActive.ShouldNotBeNull();
person.LastActive.Value.Kind.ShouldBe(DateTimeKind.Unspecified);
person.LastActive.Value.ToString("yyy-MM-dd HH:mm:ss").ShouldBe("2020-01-01 00:00:00");
}
}
}
Loading…
Cancel
Save