Skip to content

Commit

Permalink
Added option to disable UtcDateTimePropertyEntityBehavior (#6)
Browse files Browse the repository at this point in the history
Co-authored-by: Henk Kin <[email protected]>
  • Loading branch information
HenkKin and Henk Kin authored Dec 2, 2022
1 parent c6785ff commit ce05e26
Show file tree
Hide file tree
Showing 13 changed files with 75 additions and 268 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System;
using DataAccessClient.EntityFrameworkCore.SqlServer.Tests.TestModels;
using DataAccessClient.EntityFrameworkCore.SqlServer.Tests.TestModels;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking;
using Microsoft.Extensions.DependencyInjection;
Expand All @@ -24,6 +23,7 @@ public void WhenWorkIsDoneWithCascadeTimingOnSaveChanges_ItShouldResetToCascadeT
var serviceProvider = services.BuildServiceProvider().CreateScope();

var dbContext = serviceProvider.ServiceProvider.GetService<TestDbContext>();
Assert.NotNull(dbContext);

// EF Core defaults to Immediate since EF Core 3.0, before 3.0 to OnSaveChanges
// https://docs.microsoft.com/en-us/ef/core/what-is-new/ef-core-3.0/breaking-changes#cascade
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
<PackageReleaseNotes></PackageReleaseNotes>
<Copyright>Henk Kin</Copyright>
<PackageTags>EntityFrameworkCore, EF, SqlServer, DependencyInjection, Multiple DbContext support, DataAccess, Repository, UnitOfWork, SoftDelete, Translation, Localization, RowVersioning, Multitenancy, Filtering, Paging, Sorting, Includes</PackageTags>
<Version>7.0.0</Version>
<Version>7.0.1</Version>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<EmbedUntrackedSources>true</EmbedUntrackedSources>
<IncludeSymbols>true</IncludeSymbols>
Expand All @@ -23,7 +23,7 @@
<PackageReference Include="EntityCloner.Microsoft.EntityFrameworkCore" Version="7.0.0" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" />
<PackageReference Include="LinqKit.Microsoft.EntityFrameworkCore" Version="7.1.3" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Scripting" Version="4.3.1" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Scripting" Version="4.4.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="7.0.0" />
</ItemGroup>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ namespace DataAccessClient.EntityFrameworkCore.SqlServer
public class DataAccessClientOptions
{
public Action<DbContextOptionsBuilder> DbContextOptionsBuilder { get; internal set; }
public bool DisableUtcDateTimePropertyEntityBehavior { get; internal set; }
public bool UsePooling { get; internal set; }
public int? PoolSize { get; internal set; }
public IList<IEntityBehaviorConfiguration> CustomEntityBehaviors { get; internal set; } = new List<IEntityBehaviorConfiguration>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ public virtual DataAccessClientOptionsBuilder UsePooling(bool usePooling, int? p
return this;
}

public virtual DataAccessClientOptionsBuilder DisableUtcDateTimePropertyEntityBehavior()
{
_options.DisableUtcDateTimePropertyEntityBehavior = true;
return this;
}

public virtual DataAccessClientOptionsBuilder AddCustomEntityBehavior<TEntityHaviorType>() where TEntityHaviorType : IEntityBehaviorConfiguration
{
_options.CustomEntityBehaviors.Add((TEntityHaviorType)Activator.CreateInstance(typeof(TEntityHaviorType)));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@ public RestoreAction Disable()
IsEnabled = false;
return new RestoreAction(() => IsEnabled = originalIsEnabled);
}



public RestoreAction EnableQueryFilter()
{
var originalIsQueryFilterEnabled = IsQueryFilterEnabled;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using System;
using System.Linq;
using System.Linq.Expressions;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Microsoft.EntityFrameworkCore.Query;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using System;
using System.Linq;
using Microsoft.EntityFrameworkCore;

namespace DataAccessClient.EntityFrameworkCore.SqlServer.Resolvers
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,14 @@ public static IServiceCollection AddDataAccessClient<TDbContext>(this IServiceCo
CreateEntityBehaviorTypeInstance(typeof(LocalizableEntityBehaviorConfiguration<>).MakeGenericType(localeIdentifierType)),
CreateEntityBehaviorTypeInstance(typeof(TenantScopeableEntityBehaviorConfiguration<>).MakeGenericType(tenantIdentifierType)),
new TranslatableEntityBehaviorConfiguration(),
new TranslatedPropertyEntityBehaviorConfiguration(),
new UtcDateTimePropertyEntityBehaviorConfiguration()
new TranslatedPropertyEntityBehaviorConfiguration()
};

if (dataAccessClientOptions.DisableUtcDateTimePropertyEntityBehavior == false)
{
entityBehaviorConfigurations.Add(new UtcDateTimePropertyEntityBehaviorConfiguration());
}

if (dataAccessClientOptions.CustomEntityBehaviors.Any())
{
entityBehaviorConfigurations.AddRange(dataAccessClientOptions.CustomEntityBehaviors);
Expand All @@ -57,21 +61,6 @@ void ExtendedDbContextOptionsBuilder(DbContextOptionsBuilder dbContextOptionsBui
entityBehavior.OnRegistering(services);
}

//if (ContainsEntityBehaviors(dataAccessClientOptions.EntityTypes, new[] { typeof(ISoftDeletable<>) }))
//{
// services.RequireRegistrationFor<ISoftDeletableConfiguration>(ServiceLifetime.Scoped);
//}

//if (ContainsEntityBehaviors(dataAccessClientOptions.EntityTypes, new[] { typeof(ITenantScopable<>) }))
//{
// services.RequireRegistrationFor<IMultiTenancyConfiguration>(ServiceLifetime.Scoped);
//}

//if (ContainsEntityBehaviors(dataAccessClientOptions.EntityTypes, new[] { typeof(ILocalizable<>) }))
//{
// services.RequireRegistrationFor<ILocalizationConfiguration>(ServiceLifetime.Scoped);
//}

if (dataAccessClientOptions.UsePooling)
{
if (dataAccessClientOptions.PoolSize.HasValue)
Expand Down Expand Up @@ -135,243 +124,5 @@ private static Type GetLocaleIdentifierType(this IServiceCollection services)
s.Lifetime == ServiceLifetime.Scoped);
return registration?.ServiceType.GenericTypeArguments[0];
}

//private static void ValidateDataAccessClientOptions(this IServiceCollection services, DataAccessClientOptions dataAccessClientOptions, Type userIdentifierType, Type tenantIdentifierType, Type localeIdentifierType)
//{

// ValidateUserIdentifierType(services, dataAccessClientOptions, userIdentifierType);

// ValidateTenantIdentifierType(services, dataAccessClientOptions, tenantIdentifierType);

// ValidateLocaleIdentifierType(services, dataAccessClientOptions, localeIdentifierType);
//}

//internal static void ValidateTenantIdentifierType(IServiceCollection services, DataAccessClientOptions dataAccessClientOptions, Type tenantIdentifierType)
//{
// var tenantIdentifierRelatedEntityBehaviors = new[] { typeof(ITenantScopable<>) };


// bool hasEntityBehaviorsWithTenantIdentifier =
// ContainsEntityBehaviors(dataAccessClientOptions.EntityTypes, tenantIdentifierRelatedEntityBehaviors);
// if (hasEntityBehaviorsWithTenantIdentifier)
// {
// services.RequireRegistrationForGeneric(typeof(ITenantIdentifierProvider<>), ServiceLifetime.Scoped);

// var tenantIdentifierProviderType = typeof(ITenantIdentifierProvider<>).MakeGenericType(tenantIdentifierType);
// services.RequireRegistrationFor(tenantIdentifierProviderType, ServiceLifetime.Scoped);

// var entityBehaviorsWithWrongTenantIdentifierType = new Dictionary<Type, List<Type>>();
// foreach (var tenantIdentifierRelatedEntityBehavior in tenantIdentifierRelatedEntityBehaviors)
// {
// var types = GetEntityTypesWithWrongIdentifierTypeInEntityBehavior(
// dataAccessClientOptions.EntityTypes, tenantIdentifierRelatedEntityBehavior,
// tenantIdentifierType);

// if (types.Any())
// {
// if (entityBehaviorsWithWrongTenantIdentifierType.ContainsKey(tenantIdentifierRelatedEntityBehavior))
// {
// entityBehaviorsWithWrongTenantIdentifierType[tenantIdentifierRelatedEntityBehavior]
// .AddRange(types);
// }
// else
// {
// entityBehaviorsWithWrongTenantIdentifierType.Add(tenantIdentifierRelatedEntityBehavior, types);
// }
// }
// }

// if (entityBehaviorsWithWrongTenantIdentifierType.Any())
// {
// var errorMessage = new StringBuilder();
// errorMessage.AppendLine("The following entity types have implemented the entityhavior interface with a wrong user identifier type:");
// foreach (var entityBehaviorWithWrongTenantIdentifierType in entityBehaviorsWithWrongTenantIdentifierType)
// {
// errorMessage.AppendLine($"EntityBehavior: {entityBehaviorWithWrongTenantIdentifierType.Key.Name}");
// foreach (var type in entityBehaviorWithWrongTenantIdentifierType.Value)
// {
// errorMessage.AppendLine($"- {type.Name} ({type.FullName})");
// }
// }

// throw new InvalidOperationException(errorMessage.ToString());
// }
// }
//}

//internal static void ValidateUserIdentifierType(IServiceCollection services, DataAccessClientOptions dataAccessClientOptions, Type userIdentifierType)
//{
// var userIdentifierRelatedEntityBehaviors =
// new[] { typeof(ICreatable<>), typeof(IModifiable<>), typeof(ISoftDeletable<>) };


// bool hasEntityBehaviorsWithUserIdentifier =
// ContainsEntityBehaviors(dataAccessClientOptions.EntityTypes, userIdentifierRelatedEntityBehaviors);
// if (hasEntityBehaviorsWithUserIdentifier)
// {
// services.RequireRegistrationForGeneric(typeof(IUserIdentifierProvider<>), ServiceLifetime.Scoped);

// var userIdentifierProviderType = typeof(IUserIdentifierProvider<>).MakeGenericType(userIdentifierType);
// services.RequireRegistrationFor(userIdentifierProviderType, ServiceLifetime.Scoped);

// var entityBehaviorsWithWrongUserIdentifierType = new Dictionary<Type, List<Type>>();
// foreach (var userIdentifierRelatedEntityBehavior in userIdentifierRelatedEntityBehaviors)
// {
// var types = GetEntityTypesWithWrongIdentifierTypeInEntityBehavior(
// dataAccessClientOptions.EntityTypes, userIdentifierRelatedEntityBehavior,
// userIdentifierType);

// if (types.Any())
// {
// if (entityBehaviorsWithWrongUserIdentifierType.ContainsKey(userIdentifierRelatedEntityBehavior))
// {
// entityBehaviorsWithWrongUserIdentifierType[userIdentifierRelatedEntityBehavior]
// .AddRange(types);
// }
// else
// {
// entityBehaviorsWithWrongUserIdentifierType.Add(userIdentifierRelatedEntityBehavior, types);
// }
// }
// }

// if (entityBehaviorsWithWrongUserIdentifierType.Any())
// {
// var errorMessage = new StringBuilder();
// errorMessage.AppendLine(
// $"The current UserIdentifier type is: {userIdentifierType.Name}, the following entity types have implemented the entityhavior interface with a wrong user identifier type:");
// foreach (var entityBehaviorWithWrongUserIdentifierType in entityBehaviorsWithWrongUserIdentifierType)
// {
// errorMessage.AppendLine($"EntityBehavior: {entityBehaviorWithWrongUserIdentifierType.Key.Name}");
// foreach (var type in entityBehaviorWithWrongUserIdentifierType.Value)
// {
// errorMessage.AppendLine($"- {type.Name} ({type.FullName})");
// }
// }

// throw new InvalidOperationException(errorMessage.ToString());
// }
// }
//}

//internal static void ValidateLocaleIdentifierType(IServiceCollection services, DataAccessClientOptions dataAccessClientOptions, Type localeIdentifierType)
//{
// var localeIdentifierRelatedEntityBehaviors =
// new[] { typeof(ILocalizable<>) };

// bool hasEntityBehaviorsWithLocaleIdentifier =
// ContainsEntityBehaviors(dataAccessClientOptions.EntityTypes, localeIdentifierRelatedEntityBehaviors);
// if (hasEntityBehaviorsWithLocaleIdentifier)
// {
// services.RequireRegistrationForGeneric(typeof(ILocaleIdentifierProvider<>), ServiceLifetime.Scoped);

// var localeIdentifierProviderType = typeof(ILocaleIdentifierProvider<>).MakeGenericType(localeIdentifierType);
// services.RequireRegistrationFor(localeIdentifierProviderType, ServiceLifetime.Scoped);

// var entityBehaviorsWithWrongLocaleIdentifierType = new Dictionary<Type, List<Type>>();
// foreach (var localeIdentifierRelatedEntityBehavior in localeIdentifierRelatedEntityBehaviors)
// {
// var types = GetEntityTypesWithWrongIdentifierTypeInEntityBehavior(
// dataAccessClientOptions.EntityTypes, localeIdentifierRelatedEntityBehavior,
// localeIdentifierType);

// if (types.Any())
// {
// if (entityBehaviorsWithWrongLocaleIdentifierType.ContainsKey(localeIdentifierRelatedEntityBehavior))
// {
// entityBehaviorsWithWrongLocaleIdentifierType[localeIdentifierRelatedEntityBehavior]
// .AddRange(types);
// }
// else
// {
// entityBehaviorsWithWrongLocaleIdentifierType.Add(localeIdentifierRelatedEntityBehavior, types);
// }
// }
// }

// if (entityBehaviorsWithWrongLocaleIdentifierType.Any())
// {
// var errorMessage = new StringBuilder();
// errorMessage.AppendLine(
// $"The current LocaleIdentifier type is: {localeIdentifierType.Name}, the following entity types have implemented the entityhavior interface with a wrong locale identifier type:");
// foreach (var entityBehaviorWithWrongLocaleIdentifierType in entityBehaviorsWithWrongLocaleIdentifierType)
// {
// errorMessage.AppendLine($"EntityBehavior: {entityBehaviorWithWrongLocaleIdentifierType.Key.Name}");
// foreach (var type in entityBehaviorWithWrongLocaleIdentifierType.Value)
// {
// errorMessage.AppendLine($"- {type.Name} ({type.FullName})");
// }
// }

// throw new InvalidOperationException(errorMessage.ToString());
// }
// }
//}

////private static void RequireRegistrationFor<TRegistrationType>(this IServiceCollection services,
//// ServiceLifetime serviceLifetime)
////{
//// var isRegisteredWithLifetime =
//// services.Any(s =>
//// s.ServiceType == typeof(TRegistrationType) &&
//// s.Lifetime == serviceLifetime);
//// if (!isRegisteredWithLifetime)
//// {
//// ThrowNoRegistrationFoundException(typeof(TRegistrationType), serviceLifetime);
//// }
////}


//private static void RequireRegistrationForGeneric(this IServiceCollection services, Type registrationType, ServiceLifetime serviceLifetime)
//{
// var isRegisteredWithLifetime =
// services.Any(s =>
// s.ServiceType.IsGenericType &&
// s.ServiceType.GetGenericTypeDefinition() == registrationType &&
// s.Lifetime == serviceLifetime);
// if (!isRegisteredWithLifetime)
// {
// ThrowNoRegistrationFoundException(registrationType, serviceLifetime);
// }
//}

//private static void RequireRegistrationFor(this IServiceCollection services, Type registrationType, ServiceLifetime serviceLifetime)
//{
// var isRegisteredWithLifetime =
// services.Any(s =>
// s.ServiceType == registrationType &&
// s.Lifetime == serviceLifetime);
// if (!isRegisteredWithLifetime)
// {
// ThrowNoRegistrationFoundException(registrationType, serviceLifetime);
// }
//}

//private static void ThrowNoRegistrationFoundException(Type registrationType, ServiceLifetime serviceLifetime)
//{
// throw new InvalidOperationException(
// $"No DI registration found for type {registrationType.FullName}, please register with LifeTime {serviceLifetime.ToString()} in DI");

//}

//private static bool ContainsEntityBehaviors(Type[] entityTypes, Type[] entityBehaviors = null)
//{
// var containsEntityBehaviors = entityBehaviors != null && entityTypes
// .Any(c => c.GetInterfaces().Any(i =>
// i.IsGenericType && entityBehaviors.Contains(i.GetGenericTypeDefinition())));

// return containsEntityBehaviors;
//}

//private static List<Type> GetEntityTypesWithWrongIdentifierTypeInEntityBehavior(Type[] entityTypes, Type entityBehavior, Type identifierType)
//{
// var entityTypesWithWrongIdentifierTypeInEntityBehavior = entityTypes
// .Where(c => c.GetInterfaces().Any(i =>
// i.IsGenericType &&
// i.GetGenericTypeDefinition() == entityBehavior &&
// i.GenericTypeArguments[0] != identifierType)).ToList();

// return entityTypesWithWrongIdentifierTypeInEntityBehavior;
//}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
using Microsoft.Data.SqlClient;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Internal;

namespace DataAccessClient.EntityFrameworkCore.SqlServer
{
Expand Down
Loading

0 comments on commit ce05e26

Please sign in to comment.