From edf65f971122845c76217013654fb6e6b4b74bcf Mon Sep 17 00:00:00 2001 From: Marc Wittke Date: Wed, 8 Jun 2022 13:13:39 -0300 Subject: [PATCH 1/3] call .ClrType via reflection to work around breaking change in EFCore 6.0 --- .../DbContextExtensions.cs | 14 ++++++++++---- .../Backend.Fx.EfCorePersistence/EfFlush.cs | 2 +- .../Backend.Fx.EfCorePersistence/EfRepository.cs | 2 +- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/implementations/Backend.Fx.EfCorePersistence/DbContextExtensions.cs b/src/implementations/Backend.Fx.EfCorePersistence/DbContextExtensions.cs index 35668e25..4f48b23a 100644 --- a/src/implementations/Backend.Fx.EfCorePersistence/DbContextExtensions.cs +++ b/src/implementations/Backend.Fx.EfCorePersistence/DbContextExtensions.cs @@ -7,6 +7,7 @@ using Backend.Fx.Logging; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.ChangeTracking; +using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.Extensions.Logging; using ILogger = Microsoft.Extensions.Logging.ILogger; @@ -27,16 +28,16 @@ public static void RegisterRowVersionProperty(this ModelBuilder modelBuilder) { modelBuilder.Model .GetEntityTypes() - .Where(mt => typeof(Entity).GetTypeInfo().IsAssignableFrom(mt.ClrType.GetTypeInfo())) - .ForAll(mt => modelBuilder.Entity(mt.ClrType).Property("RowVersion").IsRowVersion()); + .Where(mt => typeof(Entity).GetTypeInfo().IsAssignableFrom(mt.GetClrType().GetTypeInfo())) + .ForAll(mt => modelBuilder.Entity(mt.GetClrType()).Property("RowVersion").IsRowVersion()); } public static void RegisterEntityIdAsNeverGenerated(this ModelBuilder modelBuilder) { modelBuilder.Model .GetEntityTypes() - .Where(mt => typeof(Entity).GetTypeInfo().IsAssignableFrom(mt.ClrType.GetTypeInfo())) - .ForAll(mt => modelBuilder.Entity(mt.ClrType).Property(nameof(Entity.Id)).ValueGeneratedNever()); + .Where(mt => typeof(Entity).GetTypeInfo().IsAssignableFrom(mt.GetClrType().GetTypeInfo())) + .ForAll(mt => modelBuilder.Entity(mt.GetClrType()).Property(nameof(Entity.Id)).ValueGeneratedNever()); } public static void ApplyAggregateMappings(this DbContext dbContext, ModelBuilder modelBuilder) @@ -83,5 +84,10 @@ private static string GetPrimaryKeyValue(EntityEntry entry) { return (entry.Entity as Entity)?.Id.ToString(CultureInfo.InvariantCulture) ?? "?"; } + + internal static Type GetClrType(this IEntityType mt) + { + return (Type) mt.GetType().GetProperty("ClrType")!.GetValue(mt); + } } } \ No newline at end of file diff --git a/src/implementations/Backend.Fx.EfCorePersistence/EfFlush.cs b/src/implementations/Backend.Fx.EfCorePersistence/EfFlush.cs index c9b25368..8f532860 100644 --- a/src/implementations/Backend.Fx.EfCorePersistence/EfFlush.cs +++ b/src/implementations/Backend.Fx.EfCorePersistence/EfFlush.cs @@ -155,7 +155,7 @@ private static EntityEntry GetAggregateRootEntry(ChangeTracker changeTracker, En Logger.LogDebug("Searching aggregate root of {EntityTypeName}[{Id}]", entry.Entity.GetType().Name, (entry.Entity as Identified)?.Id); foreach (NavigationEntry navigation in entry.Navigations) { - TypeInfo navTargetTypeInfo = navigation.Metadata.TargetEntityType.ClrType.GetTypeInfo(); + TypeInfo navTargetTypeInfo = navigation.Metadata.TargetEntityType.GetClrType().GetTypeInfo(); int navigationTargetForeignKeyValue; if (navigation.CurrentValue == null) diff --git a/src/implementations/Backend.Fx.EfCorePersistence/EfRepository.cs b/src/implementations/Backend.Fx.EfCorePersistence/EfRepository.cs index 03258217..7c82d6e1 100644 --- a/src/implementations/Backend.Fx.EfCorePersistence/EfRepository.cs +++ b/src/implementations/Backend.Fx.EfCorePersistence/EfRepository.cs @@ -116,7 +116,7 @@ protected override IQueryable RawAggregateQueryable [SuppressMessage("ReSharper", "EF1001")] private void AuthorizeChanges(InternalEntityEntry entry, EntityState previousState) { - if (previousState == EntityState.Unchanged && entry.EntityState == EntityState.Modified && entry.EntityType.ClrType == typeof(TAggregateRoot)) + if (previousState == EntityState.Unchanged && entry.EntityState == EntityState.Modified && entry.EntityType.GetClrType() == typeof(TAggregateRoot)) { var aggregateRoot = (TAggregateRoot) entry.Entity; if (!_aggregateAuthorization.CanModify(aggregateRoot)) throw new ForbiddenException("Unauthorized attempt to modify {AggregateTypeName}[{aggregateRoot.Id}]") From 98f421339d84bf3f9031f24002a0839f6fa3a0f6 Mon Sep 17 00:00:00 2001 From: Marc Wittke Date: Wed, 8 Jun 2022 14:52:16 -0300 Subject: [PATCH 2/3] better null safety --- .../Backend.Fx.EfCorePersistence/DbContextExtensions.cs | 9 +++++++-- .../Backend.Fx.EfCorePersistence/EfFlush.cs | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/implementations/Backend.Fx.EfCorePersistence/DbContextExtensions.cs b/src/implementations/Backend.Fx.EfCorePersistence/DbContextExtensions.cs index 4f48b23a..4395c49a 100644 --- a/src/implementations/Backend.Fx.EfCorePersistence/DbContextExtensions.cs +++ b/src/implementations/Backend.Fx.EfCorePersistence/DbContextExtensions.cs @@ -1,10 +1,12 @@ using System; +using System.Diagnostics; using System.Globalization; using System.Linq; using System.Reflection; using Backend.Fx.BuildingBlocks; using Backend.Fx.Extensions; using Backend.Fx.Logging; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.ChangeTracking; using Microsoft.EntityFrameworkCore.Metadata; @@ -85,9 +87,12 @@ private static string GetPrimaryKeyValue(EntityEntry entry) return (entry.Entity as Entity)?.Id.ToString(CultureInfo.InvariantCulture) ?? "?"; } - internal static Type GetClrType(this IEntityType mt) + internal static Type GetClrType([NotNull] this IEntityType mt) { - return (Type) mt.GetType().GetProperty("ClrType")!.GetValue(mt); + if (mt == null) throw new ArgumentNullException(nameof(mt)); + var propertyInfo = mt.GetType().GetProperty("ClrType"); + Debug.Assert(propertyInfo != null); + return (Type) propertyInfo.GetValue(mt); } } } \ No newline at end of file diff --git a/src/implementations/Backend.Fx.EfCorePersistence/EfFlush.cs b/src/implementations/Backend.Fx.EfCorePersistence/EfFlush.cs index 8f532860..7679531b 100644 --- a/src/implementations/Backend.Fx.EfCorePersistence/EfFlush.cs +++ b/src/implementations/Backend.Fx.EfCorePersistence/EfFlush.cs @@ -155,7 +155,6 @@ private static EntityEntry GetAggregateRootEntry(ChangeTracker changeTracker, En Logger.LogDebug("Searching aggregate root of {EntityTypeName}[{Id}]", entry.Entity.GetType().Name, (entry.Entity as Identified)?.Id); foreach (NavigationEntry navigation in entry.Navigations) { - TypeInfo navTargetTypeInfo = navigation.Metadata.TargetEntityType.GetClrType().GetTypeInfo(); int navigationTargetForeignKeyValue; if (navigation.CurrentValue == null) @@ -175,6 +174,7 @@ private static EntityEntry GetAggregateRootEntry(ChangeTracker changeTracker, En // assumption: an entity cannot be loaded on its own. Everything on the navigation path starting from the // aggregate root must have been loaded before, therefore we can find it using the change tracker + TypeInfo navTargetTypeInfo = navigation.Metadata.TargetEntityType.GetClrType().GetTypeInfo(); var navigationTargetEntry = changeTracker .Entries() .Single(ent => Equals(ent.Entity.GetType().GetTypeInfo(), navTargetTypeInfo) From e0891b30ff14be995aac06073e8f7072c04cfccc Mon Sep 17 00:00:00 2001 From: Marc Wittke Date: Wed, 8 Jun 2022 15:04:37 -0300 Subject: [PATCH 3/3] compatibility with ef core 5.0 and 6.0 --- .../DbContextExtensions.cs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/implementations/Backend.Fx.EfCorePersistence/DbContextExtensions.cs b/src/implementations/Backend.Fx.EfCorePersistence/DbContextExtensions.cs index 4395c49a..8ca15084 100644 --- a/src/implementations/Backend.Fx.EfCorePersistence/DbContextExtensions.cs +++ b/src/implementations/Backend.Fx.EfCorePersistence/DbContextExtensions.cs @@ -87,12 +87,17 @@ private static string GetPrimaryKeyValue(EntityEntry entry) return (entry.Entity as Entity)?.Id.ToString(CultureInfo.InvariantCulture) ?? "?"; } - internal static Type GetClrType([NotNull] this IEntityType mt) + internal static Type GetClrType([NotNull] this IMutableEntityType met) { - if (mt == null) throw new ArgumentNullException(nameof(mt)); - var propertyInfo = mt.GetType().GetProperty("ClrType"); + if (met == null) throw new ArgumentNullException(nameof(met)); + var propertyInfo = met.GetType().GetProperty("ClrType"); Debug.Assert(propertyInfo != null); - return (Type) propertyInfo.GetValue(mt); + return (Type) propertyInfo.GetValue(met); + } + + internal static Type GetClrType([NotNull] this IEntityType et) + { + return et.ClrType; } } } \ No newline at end of file