【发布时间】:2019-11-27 22:48:25
【问题描述】:
我正在尝试在 EF Core 3.0 中使用 Global Query Filters。总的来说,他们工作得相当好,但有一个小问题。我一直在尝试以类似于指南here 的方式设置多租户。我的用例有点不同,因为租户是从查询字符串参数(或标头)派生的,并且在请求之间会发生变化。
如果我使用名为Organization 的成员定义接口IOrganizationEntity。我可以使用语句entity.HasQueryFilter<IOrganizationEntity>(o => o.Organization == OrganizationId) 定义全局查询过滤器,这可以按预期工作。但是,我试图避免在我的实体 POCO 上放置 Organization 属性,而是尝试使用类似于:
private Guid OrganizationId => HasOrganization ? _organizationService.GetCurrentOrganizationId() : Guid.Empty;
private void ConfigureOrganizationFilter(ModelBuilder modelBuilder)
{
foreach (var entity in modelBuilder.Model.GetEntityTypes().Where(x =>
typeof(IOrganizationEntity).IsAssignableFrom(x.ClrType)))
{
entity.AddProperty(nameof(Organization), typeof(Guid));
// Note, AddQueryFilter is an extension method that allows us to add multiple
// query filters to a single type of entity.
entity.AddQueryFilter(IsOrganizationRestricted(entity.ClrType));
}
}
private LambdaExpression IsOrganizationRestricted(Type type)
{
var propertyMethod = typeof(EF).GetMethod(nameof(EF.Property),
BindingFlags.Static |
BindingFlags.Public)?.MakeGenericMethod(typeof(Guid));
if (propertyMethod == null)
throw new ArgumentException("Object does not appear to be valid for operation.");
var param = Expression.Parameter(type, "it");
var prop = Expression.Call(propertyMethod, param, Expression.Constant(nameof(Organization)));
var condition = Expression.MakeBinary(ExpressionType.Equal, prop, Expression.Constant(OrganizationId));
var lambda = Expression.Lambda(condition, param);
return lambda;
}
但是,当我使用上述代码时,过滤在第一次运行时按预期工作,但在 OrganizationId 已更改的后续运行中失败。我对明确编写 Expression 函数还很陌生,所以我不确定需要发生什么来强制重新评估 OrganizationId
【问题讨论】:
-
写出如果手动完成表达式会是什么样子,并将其用作模板来动态构建表达式。
标签: c# entity-framework lambda entity-framework-core