C# 创建一个比较两个成员属性的 LambdaExpression(对于 EF Core HasQueryFilter)

Mar*_*ndl 2 .net c# entity-framework entity-framework-core .net-core

我尝试在OnModelCreating方法(Entity Framework Core)中为具有ClientId属性(int)的所有实体应用查询过滤器。到目前为止,我能够过滤实体,但我很难为这些实体调用 HasQueryFilter。

过滤器应将ClientId当前实体的属性与名为 的服务的属性进行比较ITenantProvider

这是我手动执行的方法:

modelBuilder.Entity<MyEntity>().HasQueryFilter(a => a.ClientId == _tenantProvider.TenantId);
Run Code Online (Sandbox Code Playgroud)

不幸的是,没有 Generic 的 EF CoreHasQueryFilter方法采用LambdaExpression

public virtual EntityTypeBuilder HasQueryFilter([CanBeNullAttribute] LambdaExpression filter);
Run Code Online (Sandbox Code Playgroud)

我不知道如何将上述调用转换为 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

这基本上适用于第一次调用,但由于我使用Expression.Constant它,如果发生更改,它不适用于下一个请求_tenantProvider.TenantId

如何在运行时比较实体ClientId属性_tenantProvider.TenantId

Iva*_*oev 5

获得相当于的运行时表达式的最简单方法

_tenantProvider.TenantId
Run Code Online (Sandbox Code Playgroud)

是构建一个编译时无参数 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);
Run Code Online (Sandbox Code Playgroud)