diff --git a/XCode/Membership/ITenantSource.cs b/XCode/Membership/ITenantSource.cs
index 51e99d8e5..eb647b01f 100644
--- a/XCode/Membership/ITenantSource.cs
+++ b/XCode/Membership/ITenantSource.cs
@@ -189,4 +189,14 @@ protected override Boolean OnValid(IEntity entity, DataMethod method)
return true;
}
+
+ /// 查询时自动附加租户过滤条件,无需在业务代码中手动调用 ApplyTenant
+ /// 实体工厂
+ /// 查询条件表达式
+ /// 查询操作来源
+ /// 修改后的查询条件,已合并租户过滤
+ protected override XCode.Expression? OnQuery(IEntityFactory factory, XCode.Expression? where, QueryAction action)
+ {
+ return (where & XCode.Expression.Empty).ApplyTenant(factory);
+ }
}
diff --git a/XUnitTest.XCode/Membership/TenantContextTests.cs b/XUnitTest.XCode/Membership/TenantContextTests.cs
index 492657bce..b169ba334 100644
--- a/XUnitTest.XCode/Membership/TenantContextTests.cs
+++ b/XUnitTest.XCode/Membership/TenantContextTests.cs
@@ -324,6 +324,100 @@ public void TenantModule_OnValid_Delete_MismatchTenantId_ThrowsException()
}
#endregion
+ #region TenantModule.OnQuery 测试
+ [Fact]
+ [DisplayName("OnQuery_有租户上下文时FindAll空查询自动追加TenantId条件")]
+ public void TenantModule_OnQuery_WithContext_FindAllNullWhere_AddsTenantFilter()
+ {
+ // Arrange
+ var module = new TenantInterceptor();
+ TenantContext.Current = new TenantContext { TenantId = 123 };
+ var factory = TenantTestEntity.Meta.Factory;
+
+ // Act
+ var result = module.Query(factory, null, QueryAction.FindAll);
+
+ // Assert
+ var sql = result.ToString();
+ Assert.Contains("TenantId", sql);
+ Assert.Contains("123", sql);
+ }
+
+ [Fact]
+ [DisplayName("OnQuery_有租户上下文时Find空查询自动追加TenantId条件")]
+ public void TenantModule_OnQuery_WithContext_FindNullWhere_AddsTenantFilter()
+ {
+ // Arrange
+ var module = new TenantInterceptor();
+ TenantContext.Current = new TenantContext { TenantId = 321 };
+ var factory = TenantTestEntity.Meta.Factory;
+
+ // Act
+ var result = module.Query(factory, null, QueryAction.Find);
+
+ // Assert
+ var sql = result.ToString();
+ Assert.Contains("TenantId", sql);
+ Assert.Contains("321", sql);
+ }
+
+ [Fact]
+ [DisplayName("OnQuery_有租户且已有WhereExpression时合并租户条件")]
+ public void TenantModule_OnQuery_WithTenantAndWhereExpression_MergesTenantFilter()
+ {
+ // Arrange
+ var module = new TenantInterceptor();
+ TenantContext.Current = new TenantContext { TenantId = 456 };
+ var factory = TenantTestEntity.Meta.Factory;
+ var where = new WhereExpression();
+ where &= TenantTestEntity._.Name == "Stone";
+
+ // Act
+ var result = module.Query(factory, where, QueryAction.FindAll);
+
+ // Assert
+ var sql = result.ToString();
+ Assert.Contains("Name", sql);
+ Assert.Contains("Stone", sql);
+ Assert.Contains("TenantId", sql);
+ Assert.Contains("456", sql);
+ }
+
+ [Fact]
+ [DisplayName("OnQuery_TenantId为0时不过滤可见全部")]
+ public void TenantModule_OnQuery_TenantIdZero_DoesNotAddTenantFilter()
+ {
+ // Arrange
+ var module = new TenantInterceptor();
+ TenantContext.Current = new TenantContext { TenantId = 0 };
+ var factory = TenantTestEntity.Meta.Factory;
+
+ // Act
+ var result = module.Query(factory, null, QueryAction.FindAll);
+
+ // Assert
+ Assert.True(result.IsEmpty);
+ }
+
+ [Fact]
+ [DisplayName("OnQuery_无租户上下文时不报错且不追加TenantId条件")]
+ public void TenantModule_OnQuery_WithoutContext_DoesNotThrow()
+ {
+ // Arrange
+ var module = new TenantInterceptor();
+ TenantContext.Current = null!;
+ var factory = TenantTestEntity.Meta.Factory;
+
+ // Act
+ var error = Record.Exception(() => module.Query(factory, null, QueryAction.FindAll));
+ var result = module.Query(factory, null, QueryAction.FindAll);
+
+ // Assert
+ Assert.Null(error);
+ Assert.True(result.IsEmpty);
+ }
+ #endregion
+
#region TenantSourceHelper.ApplyTenant 测试
[Fact]
[DisplayName("ApplyTenant_有租户上下文时添加条件")]