c# - 编写一个在 DbContext 重新评估之间重新评估的 LambdaExpression?
问题描述
我正在尝试使用EF Core 3.0 中的全局查询过滤器。总的来说,他们工作得相当好,但有一个小问题。我一直在尝试以类似于此处指南的方式设置多租户。我的用例有点不同,因为租户是从查询字符串参数(或标头)派生的,并且在请求之间会发生变化。
如果我IOrganizationEntity
用一个名为Organization
. 我可以使用语句定义全局查询过滤器entity.HasQueryFilter<IOrganizationEntity>(o => o.Organization == OrganizationId)
,这可以按预期工作。但是,我试图避免Organization
在我的实体 POCO 上放置一个属性,而是尝试使用类似于:
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
解决方案
为了重新评估,过滤器表达式必须访问 db 上下文派生类的属性/字段/方法。
假设有问题的代码位于您的数据库上下文派生类中,即OrganizationId
是该类的属性,问题是
Expression.Constant(OrganizationId)
在您构建过滤器时对其进行评估,并将一个常量值绑定到过滤器表达式中。
相反,您应该像这样绑定OrganizationId
属性访问器表达式(即Expression.Property
):
// this.OrganizationId
Expression.Property(Expression.Constant(this), nameof(OrganizationId))
推荐阅读
- spring-boot - thenThrow() 不抛出异常
- macos - 从 rtf 文件在终端中运行文本行
- php - 有没有办法在 dompdf 中添加边距或缩放?
- git - 通过 OneDrive 在 2 台不同的计算机上使用 Git
- android - Android多文件下载同时更新ui
- excel - 无法从 .range.value 中获取价值
- java - 基于postgres查询的Spring数据jpa规范
- javascript - react JS中的分页
- python - 如何仅从给定的起点将文本文件中的数据附加到列表中,而不是使用 python 附加完整文件
- google-chrome - 使用 Chrome 扩展来调整未停靠的开发工具窗口的大小