diff --git a/backend/WorkClub.Infrastructure/Data/Interceptors/TenantDbConnectionInterceptor.cs b/backend/WorkClub.Infrastructure/Data/Interceptors/TenantDbConnectionInterceptor.cs index b7e8623..4acce9c 100644 --- a/backend/WorkClub.Infrastructure/Data/Interceptors/TenantDbConnectionInterceptor.cs +++ b/backend/WorkClub.Infrastructure/Data/Interceptors/TenantDbConnectionInterceptor.cs @@ -1,3 +1,4 @@ +using System.Data; using System.Data.Common; using Microsoft.AspNetCore.Http; using Microsoft.EntityFrameworkCore.Diagnostics; @@ -63,14 +64,40 @@ public class TenantDbConnectionInterceptor : DbCommandInterceptor if (!string.IsNullOrWhiteSpace(tenantId) && command.Connection is NpgsqlConnection conn) { - // Prepend SET LOCAL to set tenant context - // Note: EF Core creates implicit transactions for queries, so SET LOCAL will work - command.CommandText = $"SET LOCAL app.current_tenant_id = '{tenantId}'; " + command.CommandText; - _logger.LogInformation("SetTenantContext: Prepended SET LOCAL for tenant {TenantId}", tenantId); + try + { + // If no transaction exists AND connection is open, start one + // SET LOCAL only persists within a transaction, so we need explicit transaction scope + if (command.Transaction == null && conn.State == ConnectionState.Open) + { + command.Transaction = (NpgsqlTransaction)conn.BeginTransaction(); + _logger.LogInformation("SetTenantContext: Started transaction for tenant context"); + } + + // Execute SET LOCAL as a separate command on the same connection + // This ensures the session variable is properly set before the main query executes + using var setLocalCmd = conn.CreateCommand(); + setLocalCmd.CommandText = $"SET LOCAL app.current_tenant_id = '{tenantId}'"; + + // Use the same transaction if one exists (which it should now) + if (command.Transaction is NpgsqlTransaction transaction) + { + setLocalCmd.Transaction = transaction; + } + + // Execute synchronously (safe in interceptor context) + setLocalCmd.ExecuteNonQuery(); + _logger.LogInformation("SetTenantContext: Executed SET LOCAL for tenant {TenantId}", tenantId); + } + catch (Exception ex) + { + _logger.LogError(ex, "SetTenantContext: Failed to execute SET LOCAL for tenant {TenantId}", tenantId); + throw; + } } else { - _logger.LogWarning("ReaderExecuting: No tenant context available (tenantId={TenantId})", tenantId ?? "null"); + _logger.LogWarning("SetTenantContext: No tenant context available (tenantId={TenantId})", tenantId ?? "null"); } } }