我尝试在OnModelCreating
方法(实体框架核心)中对具有ClientId
属性(int)的所有实体应用查询过滤器。到目前为止,我已经能够过滤实体,但是我很难为这些实体调用HasQueryFilter。
过滤器应将当前实体的ClientId
属性与服务ITenantProvider
中的属性进行比较。
这是我手动执行的操作:
modelBuilder.Entity<MyEntity>().HasQueryFilter(a => a.ClientId == _tenantProvider.TenantId);
不幸的是,没有Generic的EF Core HasQueryFilter
方法采用了LambdaExpression
:
public virtual EntityTypeBuilder HasQueryFilter([CanBeNullAttribute] LambdaExpression filter);
我不知道如何将上述调用转换为Lambda表达式。我当前的代码如下:
foreach (var entityType in modelBuilder.Model.GetEntityTypes().Where(e =>
e.GetProperties().Select(property => property.Name).Any(pName => pName.Equals("ClientId"))))
{
var clientId = entityType.FindProperty("ClientId");
if (clientId != null && clientId.ClrType == typeof(int))
{
var parameter = Expression.Parameter(entityType.ClrType, "p");
var filter = Expression.Lambda(Expression.Equal(Expression.Property(parameter, clientId.PropertyInfo), Expression.Constant(_tenantProvider.TenantId), parameter);
entityType.QueryFilter = filter;
}
}
基本上,这适用于第一个呼叫,但是由于我使用Expression.Constant
,因此如果_tenantProvider.TenantId
发生更改,则不适用于下一个请求。
如何在运行时将Entity ClientId
属性与_tenantProvider.TenantId
进行比较?
答案 0 :(得分:4)
获得等效于运行时表达式的最简单方法
_tenantProvider.TenantId
是构建一个编译时无参数的lambda表达式并获取其Body:
var parameter = Expression.Parameter(entityType.ClrType, "p");
var left = Expression.Property(parameter, clientId.PropertyInfo);
Expression<Func<int>> tenantId = () => _tenantProvider.TenantId;
var right = tenantId.Body;
var filter = Expression.Lambda(Expression.Equal(left, right), parameter);
答案 1 :(得分:1)
假设TenantProvider的实例不变:
然后代替您可以使用的常量表达式
Google Sign-In
如果在某个时候重新实例化,它将不再起作用。
假设您有一些提供Tennant ID的静态属性,则可以使用:
sub