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

时间:2018-12-14 09:52:04

标签: c# .net entity-framework .net-core entity-framework-core

我尝试在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进行比较?

2 个答案:

答案 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