Browse Source

Add ConfigureJsonConversionWithValueComparer extension method.

pull/2462/head
maliming 7 years ago
parent
commit
8f74373f5f
  1. 148
      framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs
  2. 11
      framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/Modeling/AbpEntityTypeBuilderExtensions.cs
  3. 28
      framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/Modeling/AbpPropertyBuilderExtensions.cs
  4. 7
      modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/EntityFrameworkCore/IdentityServerDbContextModelCreatingExtensions.cs

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

@ -11,13 +11,13 @@ using Microsoft.EntityFrameworkCore.ChangeTracking;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Newtonsoft.Json;
using Volo.Abp.Auditing;
using Volo.Abp.Data;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Entities;
using Volo.Abp.Domain.Entities.Events;
using Volo.Abp.EntityFrameworkCore.EntityHistory;
using Volo.Abp.EntityFrameworkCore.Modeling;
using Volo.Abp.EntityFrameworkCore.ValueConverters;
using Volo.Abp.Guids;
using Volo.Abp.MultiTenancy;
@ -352,151 +352,9 @@ namespace Volo.Abp.EntityFrameworkCore
return;
}
ConfigureConcurrencyStampProperty<TEntity>(modelBuilder, mutableEntityType);
ConfigureExtraProperties<TEntity>(modelBuilder, mutableEntityType);
ConfigureAuditProperties<TEntity>(modelBuilder, mutableEntityType);
ConfigureTenantIdProperty<TEntity>(modelBuilder, mutableEntityType);
ConfigureGlobalFilters<TEntity>(modelBuilder, mutableEntityType);
}
protected virtual void ConfigureConcurrencyStampProperty<TEntity>(ModelBuilder modelBuilder, IMutableEntityType mutableEntityType)
where TEntity : class
{
if (!typeof(IHasConcurrencyStamp).IsAssignableFrom(typeof(TEntity)))
{
return;
}
modelBuilder.Entity<TEntity>(b =>
{
b.Property(x => ((IHasConcurrencyStamp) x).ConcurrencyStamp)
.IsConcurrencyToken()
.HasColumnName(nameof(IHasConcurrencyStamp.ConcurrencyStamp));
});
}
protected virtual void ConfigureExtraProperties<TEntity>(ModelBuilder modelBuilder, IMutableEntityType mutableEntityType)
where TEntity : class
{
if (!typeof(IHasExtraProperties).IsAssignableFrom(typeof(TEntity)))
{
return;
}
modelBuilder.Entity<TEntity>(b =>
{
b.Property(x => ((IHasExtraProperties) x).ExtraProperties)
.HasConversion(
d => JsonConvert.SerializeObject(d, Formatting.None),
s => JsonConvert.DeserializeObject<Dictionary<string, object>>(s)
)
.HasColumnName(nameof(IHasExtraProperties.ExtraProperties))
.Metadata.SetValueComparer(new ValueComparer<Dictionary<string, object>>(
(d1, d2) => d1.SequenceEqual(d2),
d => d.Aggregate(0, (k, v) => HashCode.Combine(k, v.GetHashCode())),
d => d.ToDictionary(k => k.Key, v => v.Value)));
});
}
protected virtual void ConfigureAuditProperties<TEntity>(ModelBuilder modelBuilder, IMutableEntityType mutableEntityType)
where TEntity : class
{
if (typeof(TEntity).IsAssignableTo<IHasCreationTime>())
{
modelBuilder.Entity<TEntity>(b =>
{
b.Property(x => ((IHasCreationTime)x).CreationTime)
.IsRequired()
.HasColumnName(nameof(IHasCreationTime.CreationTime));
});
}
modelBuilder.Entity<TEntity>().ConfigureByConvention();
if (typeof(TEntity).IsAssignableTo<IMayHaveCreator>())
{
modelBuilder.Entity<TEntity>(b =>
{
b.Property(x => ((IMayHaveCreator)x).CreatorId)
.IsRequired(false)
.HasColumnName(nameof(IMayHaveCreator.CreatorId));
});
}
if (typeof(TEntity).IsAssignableTo<IMustHaveCreator>())
{
modelBuilder.Entity<TEntity>(b =>
{
b.Property(x => ((IMustHaveCreator)x).CreatorId)
.IsRequired()
.HasColumnName(nameof(IMustHaveCreator.CreatorId));
});
}
if (typeof(TEntity).IsAssignableTo<IHasModificationTime>())
{
modelBuilder.Entity<TEntity>(b =>
{
b.Property(x => ((IHasModificationTime)x).LastModificationTime)
.IsRequired(false)
.HasColumnName(nameof(IHasModificationTime.LastModificationTime));
});
}
if (typeof(TEntity).IsAssignableTo<IModificationAuditedObject>())
{
modelBuilder.Entity<TEntity>(b =>
{
b.Property(x => ((IModificationAuditedObject)x).LastModifierId)
.IsRequired(false)
.HasColumnName(nameof(IModificationAuditedObject.LastModifierId));
});
}
if (typeof(TEntity).IsAssignableTo<ISoftDelete>())
{
modelBuilder.Entity<TEntity>(b =>
{
b.Property(x => ((ISoftDelete) x).IsDeleted)
.IsRequired()
.HasDefaultValue(false)
.HasColumnName(nameof(ISoftDelete.IsDeleted));
});
}
if (typeof(TEntity).IsAssignableTo<IHasDeletionTime>())
{
modelBuilder.Entity<TEntity>(b =>
{
b.Property(x => ((IHasDeletionTime)x).DeletionTime)
.IsRequired(false)
.HasColumnName(nameof(IHasDeletionTime.DeletionTime));
});
}
if (typeof(TEntity).IsAssignableTo<IDeletionAuditedObject>())
{
modelBuilder.Entity<TEntity>(b =>
{
b.Property(x => ((IDeletionAuditedObject)x).DeleterId)
.IsRequired(false)
.HasColumnName(nameof(IDeletionAuditedObject.DeleterId));
});
}
}
protected virtual void ConfigureTenantIdProperty<TEntity>(ModelBuilder modelBuilder, IMutableEntityType mutableEntityType)
where TEntity : class
{
if (!typeof(TEntity).IsAssignableTo<IMultiTenant>())
{
return;
}
modelBuilder.Entity<TEntity>(b =>
{
b.Property(x => ((IMultiTenant)x).TenantId)
.IsRequired(false)
.HasColumnName(nameof(IMultiTenant.TenantId));
});
ConfigureGlobalFilters<TEntity>(modelBuilder, mutableEntityType);
}
protected virtual void ConfigureGlobalFilters<TEntity>(ModelBuilder modelBuilder, IMutableEntityType mutableEntityType)

11
framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/Modeling/AbpEntityTypeBuilderExtensions.cs

@ -2,13 +2,10 @@
using System.Collections.Generic;
using System.Linq;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Newtonsoft.Json;
using Volo.Abp.Auditing;
using Volo.Abp.Data;
using Volo.Abp.Domain.Entities;
using Volo.Abp.Domain.Entities.Auditing;
using Volo.Abp.MultiTenancy;
namespace Volo.Abp.EntityFrameworkCore.Modeling
@ -59,15 +56,11 @@ namespace Volo.Abp.EntityFrameworkCore.Modeling
if (b.Metadata.ClrType.IsAssignableTo<IHasExtraProperties>())
{
b.Property<Dictionary<string, object>>(nameof(IHasExtraProperties.ExtraProperties))
.HasConversion(
d => JsonConvert.SerializeObject(d, Formatting.None),
s => JsonConvert.DeserializeObject<Dictionary<string, object>>(s)
)
.HasColumnName(nameof(IHasExtraProperties.ExtraProperties))
.Metadata.SetValueComparer(new ValueComparer<Dictionary<string, object>>(
.ConfigureJsonConversionWithValueComparer(
(d1, d2) => d1.SequenceEqual(d2),
d => d.Aggregate(0, (k, v) => HashCode.Combine(k, v.GetHashCode())),
d => d.ToDictionary(k => k.Key, v => v.Value)));
d => d.ToDictionary(k => k.Key, v => v.Value));
}
}

28
framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/Modeling/AbpPropertyBuilderExtensions.cs

@ -0,0 +1,28 @@
using System;
using System.Linq.Expressions;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Newtonsoft.Json;
namespace Volo.Abp.EntityFrameworkCore.Modeling
{
public static class AbpPropertyBuilderExtensions
{
public static void ConfigureJsonConversionWithValueComparer<TPropertyType>(
this PropertyBuilder<TPropertyType> propertyBuilder,
Expression<Func<TPropertyType, TPropertyType, bool>> equalsExpression,
Expression<Func<TPropertyType, int>> hashCodeExpression,
Expression<Func<TPropertyType, TPropertyType>> snapshotExpression)
{
propertyBuilder.HasConversion(
d => JsonConvert.SerializeObject(d, Formatting.None),
s => JsonConvert.DeserializeObject<TPropertyType>(s)
)
.Metadata.SetValueComparer(new ValueComparer<TPropertyType>(
equalsExpression,
hashCodeExpression,
snapshotExpression));
}
}
}

7
modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/EntityFrameworkCore/IdentityServerDbContextModelCreatingExtensions.cs

@ -204,13 +204,10 @@ namespace Volo.Abp.IdentityServer.EntityFrameworkCore
identityResource.Property(x => x.DisplayName).HasMaxLength(IdentityResourceConsts.DisplayNameMaxLength);
identityResource.Property(x => x.Description).HasMaxLength(IdentityResourceConsts.DescriptionMaxLength);
identityResource.Property(x => x.Properties)
.HasConversion(
d => JsonConvert.SerializeObject(d, Formatting.None),
s => JsonConvert.DeserializeObject<Dictionary<string, string>>(s)
).Metadata.SetValueComparer(new ValueComparer<Dictionary<string, string>>(
.ConfigureJsonConversionWithValueComparer(
(d1, d2) => d1.SequenceEqual(d2),
d => d.Aggregate(0, (k, v) => HashCode.Combine(k, v.GetHashCode())),
d => d.ToDictionary(k => k.Key, v => v.Value)));
d => d.ToDictionary(k => k.Key, v => v.Value));
identityResource.HasMany(x => x.UserClaims).WithOne().HasForeignKey(x => x.IdentityResourceId).IsRequired();
});

Loading…
Cancel
Save