-
Notifications
You must be signed in to change notification settings - Fork 3.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Use DbFunction for global query filters.
Resolve #20062
- Loading branch information
Showing
13 changed files
with
364 additions
and
7 deletions.
There are no files selected for viewing
21 changes: 21 additions & 0 deletions
21
...re/Microsoft/Extensions/DependencyInjection/AbpEfCoreDbContextOptionsBuilderExtensions.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
using Microsoft.EntityFrameworkCore; | ||
using Microsoft.EntityFrameworkCore.Infrastructure; | ||
using Volo.Abp.EntityFrameworkCore; | ||
|
||
namespace Microsoft.Extensions.DependencyInjection; | ||
|
||
public static class AbpEfCoreDbContextOptionsBuilderExtensions | ||
{ | ||
public static DbContextOptionsBuilder AddAbpDbContextOptionsExtension(this DbContextOptionsBuilder optionsBuilder) | ||
{ | ||
((IDbContextOptionsBuilderInfrastructure) optionsBuilder).AddOrUpdateExtension(new AbpDbContextOptionsExtension()); | ||
return optionsBuilder; | ||
} | ||
|
||
public static DbContextOptionsBuilder<TContext> AddAbpDbContextOptionsExtension<TContext>(this DbContextOptionsBuilder<TContext> optionsBuilder) | ||
where TContext : DbContext | ||
{ | ||
((IDbContextOptionsBuilderInfrastructure) optionsBuilder).AddOrUpdateExtension(new AbpDbContextOptionsExtension()); | ||
return optionsBuilder; | ||
} | ||
} |
68 changes: 68 additions & 0 deletions
68
...FrameworkCore/Microsoft/Extensions/DependencyInjection/AbpEfCoreModelBuilderExtensions.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
using System.Linq.Expressions; | ||
using System.Reflection; | ||
using Microsoft.EntityFrameworkCore; | ||
using Microsoft.EntityFrameworkCore.Query.SqlExpressions; | ||
using Volo.Abp; | ||
using Volo.Abp.EntityFrameworkCore; | ||
using Volo.Abp.EntityFrameworkCore.GlobalFilters; | ||
using Volo.Abp.MultiTenancy; | ||
|
||
namespace Microsoft.Extensions.DependencyInjection; | ||
|
||
public static class AbpEfCoreModelBuilderExtensions | ||
{ | ||
public static ModelBuilder ConfigureSoftDeleteDbFunction(this ModelBuilder modelBuilder, MethodInfo methodInfo, AbpEfCoreCurrentDbContext abpEfCoreCurrentDbContext) | ||
{ | ||
modelBuilder.HasDbFunction(methodInfo) | ||
.HasTranslation(args => | ||
{ | ||
// (bool isDeleted, bool boolParam) | ||
var isDeleted = args[0]; | ||
var boolParam = args[1]; | ||
|
||
if (abpEfCoreCurrentDbContext.Context?.DataFilter.IsEnabled<ISoftDelete>() == true) | ||
{ | ||
// IsDeleted == false | ||
return new SqlBinaryExpression( | ||
ExpressionType.Equal, | ||
isDeleted, | ||
new SqlConstantExpression(Expression.Constant(false), boolParam.TypeMapping), | ||
boolParam.Type, | ||
boolParam.TypeMapping); | ||
} | ||
|
||
// empty where sql | ||
return new SqlConstantExpression(Expression.Constant(true), boolParam.TypeMapping); | ||
}); | ||
|
||
return modelBuilder; | ||
} | ||
|
||
public static ModelBuilder ConfigureMultiTenantDbFunction(this ModelBuilder modelBuilder, MethodInfo methodInfo, AbpEfCoreCurrentDbContext abpEfCoreCurrentDbContext) | ||
{ | ||
modelBuilder.HasDbFunction(methodInfo) | ||
.HasTranslation(args => | ||
{ | ||
// (Guid? tenantId, int? currentTenantId) | ||
var tenantId = args[0]; | ||
var currentTenantId = args[1]; | ||
var boolParam = args[2]; | ||
|
||
if (abpEfCoreCurrentDbContext.Context?.DataFilter.IsEnabled<IMultiTenant>() == true) | ||
{ | ||
// TenantId == CurrentTenantId | ||
return new SqlBinaryExpression( | ||
ExpressionType.Equal, | ||
tenantId, | ||
currentTenantId, | ||
boolParam.Type, | ||
boolParam.TypeMapping); | ||
} | ||
|
||
// empty where sql | ||
return new SqlConstantExpression(Expression.Constant(true), boolParam.TypeMapping); | ||
}); | ||
|
||
return modelBuilder; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
62 changes: 62 additions & 0 deletions
62
...Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContextOptionsExtension.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using Microsoft.EntityFrameworkCore.Infrastructure; | ||
using Microsoft.EntityFrameworkCore.Query; | ||
using Microsoft.Extensions.DependencyInjection; | ||
using Microsoft.Extensions.DependencyInjection.Extensions; | ||
using Volo.Abp.EntityFrameworkCore.GlobalFilters; | ||
|
||
namespace Volo.Abp.EntityFrameworkCore; | ||
|
||
public class AbpDbContextOptionsExtension : IDbContextOptionsExtension | ||
{ | ||
public void ApplyServices(IServiceCollection services) | ||
{ | ||
var serviceDescriptor = services.FirstOrDefault(x => x.ServiceType == typeof(ICompiledQueryCacheKeyGenerator)); | ||
if (serviceDescriptor != null && serviceDescriptor.ImplementationType != null) | ||
{ | ||
services.Remove(serviceDescriptor); | ||
services.AddScoped(serviceDescriptor.ImplementationType); | ||
services.Add(ServiceDescriptor.Scoped<ICompiledQueryCacheKeyGenerator>(provider => | ||
ActivatorUtilities.CreateInstance<AbpCompiledQueryCacheKeyGenerator>(provider, | ||
provider.GetRequiredService(serviceDescriptor.ImplementationType) | ||
.As<ICompiledQueryCacheKeyGenerator>()))); | ||
} | ||
|
||
services.Replace(ServiceDescriptor.Scoped<IAsyncQueryProvider, AbpEntityQueryProvider>()); | ||
services.AddSingleton(typeof(AbpEfCoreCurrentDbContext)); | ||
} | ||
|
||
public void Validate(IDbContextOptions options) | ||
{ | ||
} | ||
|
||
public DbContextOptionsExtensionInfo Info => new AbpOptionsExtensionInfo(this); | ||
|
||
private class AbpOptionsExtensionInfo : DbContextOptionsExtensionInfo | ||
{ | ||
public AbpOptionsExtensionInfo(IDbContextOptionsExtension extension) | ||
: base(extension) | ||
{ | ||
} | ||
|
||
public override bool IsDatabaseProvider => false; | ||
|
||
public override int GetServiceProviderHashCode() | ||
{ | ||
return 0; | ||
} | ||
|
||
public override bool ShouldUseSameServiceProvider(DbContextOptionsExtensionInfo other) | ||
{ | ||
return other is AbpOptionsExtensionInfo; | ||
} | ||
|
||
public override void PopulateDebugInfo(IDictionary<string, string> debugInfo) | ||
{ | ||
} | ||
|
||
public override string LogFragment => "AbpOptionsExtension"; | ||
} | ||
} |
49 changes: 49 additions & 0 deletions
49
...k/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpEntityQueryProvider.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
using System.Linq.Expressions; | ||
using System.Threading; | ||
using Microsoft.EntityFrameworkCore.Infrastructure; | ||
using Microsoft.EntityFrameworkCore.Query.Internal; | ||
using Volo.Abp.EntityFrameworkCore.GlobalFilters; | ||
|
||
namespace Volo.Abp.EntityFrameworkCore; | ||
|
||
#pragma warning disable EF1001 | ||
public class AbpEntityQueryProvider : EntityQueryProvider | ||
{ | ||
protected AbpEfCoreCurrentDbContext AbpEfCoreCurrentDbContext { get; } | ||
protected ICurrentDbContext CurrentDbContext { get; } | ||
|
||
public AbpEntityQueryProvider( | ||
IQueryCompiler queryCompiler, | ||
AbpEfCoreCurrentDbContext abpEfCoreCurrentDbContext, | ||
ICurrentDbContext currentDbContext) | ||
: base(queryCompiler) | ||
{ | ||
AbpEfCoreCurrentDbContext = abpEfCoreCurrentDbContext; | ||
CurrentDbContext = currentDbContext; | ||
} | ||
|
||
public override object Execute(Expression expression) | ||
{ | ||
using (AbpEfCoreCurrentDbContext.Use(CurrentDbContext.Context as IAbpEfCoreDbFunctionContext)) | ||
{ | ||
return base.Execute(expression); | ||
} | ||
} | ||
|
||
public override TResult Execute<TResult>(Expression expression) | ||
{ | ||
using (AbpEfCoreCurrentDbContext.Use(CurrentDbContext.Context as IAbpEfCoreDbFunctionContext)) | ||
{ | ||
return base.Execute<TResult>(expression); | ||
} | ||
} | ||
|
||
public override TResult ExecuteAsync<TResult>(Expression expression, CancellationToken cancellationToken = new CancellationToken()) | ||
{ | ||
using (AbpEfCoreCurrentDbContext.Use(CurrentDbContext.Context as IAbpEfCoreDbFunctionContext)) | ||
{ | ||
return base.ExecuteAsync<TResult>(expression, cancellationToken); | ||
} | ||
} | ||
} | ||
#pragma warning restore EF1001 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
59 changes: 59 additions & 0 deletions
59
...eworkCore/Volo/Abp/EntityFrameworkCore/GlobalFilters/AbpCompiledQueryCacheKeyGenerator.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
using System; | ||
using System.Linq.Expressions; | ||
using Microsoft.EntityFrameworkCore.Infrastructure; | ||
using Microsoft.EntityFrameworkCore.Query; | ||
|
||
namespace Volo.Abp.EntityFrameworkCore.GlobalFilters; | ||
|
||
public class AbpCompiledQueryCacheKeyGenerator : ICompiledQueryCacheKeyGenerator | ||
{ | ||
protected ICompiledQueryCacheKeyGenerator InnerCompiledQueryCacheKeyGenerator { get; } | ||
protected ICurrentDbContext CurrentContext { get; } | ||
|
||
public AbpCompiledQueryCacheKeyGenerator( | ||
ICompiledQueryCacheKeyGenerator innerCompiledQueryCacheKeyGenerator, | ||
ICurrentDbContext currentContext) | ||
{ | ||
InnerCompiledQueryCacheKeyGenerator = innerCompiledQueryCacheKeyGenerator; | ||
CurrentContext = currentContext; | ||
} | ||
|
||
public virtual object GenerateCacheKey(Expression query, bool async) | ||
{ | ||
var cacheKey = InnerCompiledQueryCacheKeyGenerator.GenerateCacheKey(query, async); | ||
if (CurrentContext.Context is IAbpEfCoreDbFunctionContext abpEfCoreDbFunctionContext) | ||
{ | ||
return new AbpCompiledQueryCacheKey(cacheKey, abpEfCoreDbFunctionContext.GetCompiledQueryCacheKey()); | ||
} | ||
|
||
return cacheKey; | ||
} | ||
|
||
private readonly struct AbpCompiledQueryCacheKey : IEquatable<AbpCompiledQueryCacheKey> | ||
{ | ||
private readonly object _compiledQueryCacheKey; | ||
private readonly string _currentFilterCacheKey; | ||
|
||
public AbpCompiledQueryCacheKey(object compiledQueryCacheKey, string currentFilterCacheKey) | ||
{ | ||
_compiledQueryCacheKey = compiledQueryCacheKey; | ||
_currentFilterCacheKey = currentFilterCacheKey; | ||
} | ||
|
||
public override bool Equals(object? obj) | ||
{ | ||
return obj is AbpCompiledQueryCacheKey key && Equals(key); | ||
} | ||
|
||
public bool Equals(AbpCompiledQueryCacheKey other) | ||
{ | ||
return _compiledQueryCacheKey.Equals(other._compiledQueryCacheKey) && | ||
_currentFilterCacheKey == other._currentFilterCacheKey; | ||
} | ||
|
||
public override int GetHashCode() | ||
{ | ||
return HashCode.Combine(_compiledQueryCacheKey, _currentFilterCacheKey); | ||
} | ||
} | ||
} |
21 changes: 21 additions & 0 deletions
21
...tityFrameworkCore/Volo/Abp/EntityFrameworkCore/GlobalFilters/AbpEfCoreCurrentDbContext.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
using System; | ||
using System.Threading; | ||
|
||
namespace Volo.Abp.EntityFrameworkCore.GlobalFilters; | ||
|
||
public class AbpEfCoreCurrentDbContext | ||
{ | ||
private readonly AsyncLocal<IAbpEfCoreDbFunctionContext?> _current = new AsyncLocal<IAbpEfCoreDbFunctionContext?>(); | ||
|
||
public IAbpEfCoreDbFunctionContext? Context => _current.Value; | ||
|
||
public IDisposable Use(IAbpEfCoreDbFunctionContext? context) | ||
{ | ||
var previousValue = Context; | ||
_current.Value = context; | ||
return new DisposeAction(() => | ||
{ | ||
_current.Value = previousValue; | ||
}); | ||
} | ||
} |
Oops, something went wrong.