From 237b22bf0ff72a13164044a918afb35be0875aeb Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Fri, 16 May 2025 21:57:49 +0200 Subject: [PATCH] Fix tenant ID handling and query filtering logic. Replaced direct query filter setup with a dedicated method for cleaner and more readable tenant ID filtering logic. Removed unnecessary dependencies and improved code consistency by aligning naming conventions and simplifying expressions. --- .../ElsaDbContextBase.cs | 16 ++++----- .../EntityHandlers/SetTenantIdFilter.cs | 33 ++++++++++++++----- 2 files changed, 32 insertions(+), 17 deletions(-) diff --git a/src/modules/Elsa.EntityFrameworkCore.Common/ElsaDbContextBase.cs b/src/modules/Elsa.EntityFrameworkCore.Common/ElsaDbContextBase.cs index 2a22f2a7d..a1f9dcb35 100644 --- a/src/modules/Elsa.EntityFrameworkCore.Common/ElsaDbContextBase.cs +++ b/src/modules/Elsa.EntityFrameworkCore.Common/ElsaDbContextBase.cs @@ -19,7 +19,7 @@ public abstract class ElsaDbContextBase : DbContext, IElsaDbContextSchema }; protected IServiceProvider ServiceProvider { get; } - private readonly ElsaDbContextOptions? _elsaDbContextOptions; + private readonly ElsaDbContextOptions? elsaDbContextOptions; public string? TenantId { get; set; } /// @@ -41,10 +41,10 @@ public abstract class ElsaDbContextBase : DbContext, IElsaDbContextSchema protected ElsaDbContextBase(DbContextOptions options, IServiceProvider serviceProvider) : base(options) { ServiceProvider = serviceProvider; - _elsaDbContextOptions = options.FindExtension()?.Options; - + elsaDbContextOptions = options.FindExtension()?.Options; + // ReSharper disable once VirtualMemberCallInConstructor - Schema = !string.IsNullOrWhiteSpace(_elsaDbContextOptions?.SchemaName) ? _elsaDbContextOptions.SchemaName : ElsaSchema; + Schema = !string.IsNullOrWhiteSpace(elsaDbContextOptions?.SchemaName) ? elsaDbContextOptions.SchemaName : ElsaSchema; var tenantAccessor = serviceProvider.GetService(); var tenantId = tenantAccessor?.Tenant?.Id; @@ -63,11 +63,11 @@ public abstract class ElsaDbContextBase : DbContext, IElsaDbContextSchema /// protected override void OnModelCreating(ModelBuilder modelBuilder) { - if (!string.IsNullOrWhiteSpace(Schema)) + if (!string.IsNullOrWhiteSpace(Schema)) modelBuilder.HasDefaultSchema(Schema); - var additionalConfigurations = _elsaDbContextOptions?.GetModelConfigurations(this); - + var additionalConfigurations = elsaDbContextOptions?.GetModelConfigurations(this); + additionalConfigurations?.Invoke(modelBuilder); using var scope = ServiceProvider.CreateScope(); @@ -75,7 +75,7 @@ public abstract class ElsaDbContextBase : DbContext, IElsaDbContextSchema foreach (var entityType in modelBuilder.Model.GetEntityTypes().ToList()) { - foreach (var handler in entityTypeHandlers) + foreach (var handler in entityTypeHandlers) handler.Handle(this, modelBuilder, entityType); } } diff --git a/src/modules/Elsa.EntityFrameworkCore.Common/EntityHandlers/SetTenantIdFilter.cs b/src/modules/Elsa.EntityFrameworkCore.Common/EntityHandlers/SetTenantIdFilter.cs index 0e5bb9d9d..f4522d7d4 100644 --- a/src/modules/Elsa.EntityFrameworkCore.Common/EntityHandlers/SetTenantIdFilter.cs +++ b/src/modules/Elsa.EntityFrameworkCore.Common/EntityHandlers/SetTenantIdFilter.cs @@ -1,9 +1,7 @@ using System.Linq.Expressions; using Elsa.Common.Entities; -using Elsa.Extensions; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Query; namespace Elsa.EntityFrameworkCore.EntityHandlers; @@ -15,15 +13,32 @@ public class SetTenantIdFilter : IEntityModelCreatingHandler /// public void Handle(ElsaDbContextBase dbContext, ModelBuilder modelBuilder, IMutableEntityType entityType) { - if (!entityType.ClrType.IsAssignableTo(typeof(Entity))) + if (!typeof(Entity).IsAssignableFrom(entityType.ClrType)) return; - var tenantId = dbContext.TenantId.NullIfEmpty(); - var parameter = Expression.Parameter(entityType.ClrType); - Expression> filterExpr = entity => entity.TenantId == tenantId; - var body = ReplacingExpressionVisitor.Replace(filterExpr.Parameters[0], parameter, filterExpr.Body); - var lambdaExpression = Expression.Lambda(body, parameter); + modelBuilder + .Entity(entityType.ClrType) + .HasQueryFilter(CreateTenantFilterExpression(dbContext, entityType.ClrType)); + } - entityType.SetQueryFilter(lambdaExpression); + private LambdaExpression CreateTenantFilterExpression(ElsaDbContextBase dbContext, Type clrType) + { + var parameter = Expression.Parameter(clrType, "e"); + + // e => EF.Property(e, "TenantId") == this.TenantId + var tenantIdProperty = Expression.Call( + typeof(EF), + nameof(EF.Property), + [typeof(string)], + parameter, + Expression.Constant("TenantId")); + + var tenantIdOnContext = Expression.Property( + Expression.Constant(dbContext), + nameof(ElsaDbContextBase.TenantId)); + + var body = Expression.Equal(tenantIdProperty, tenantIdOnContext); + + return Expression.Lambda(body, parameter); } } \ No newline at end of file