C # Создайте выражение LambdaExpression, которое сравнивает два свойства члена (для EF Core HasQueryFilter) - PullRequest
0 голосов
/ 14 декабря 2018

Я пытаюсь применить фильтр запросов в методе OnModelCreating (Entity Framework Core) для всех сущностей, которые имеют свойство ClientId (int).Пока я могу фильтровать объекты, но я пытаюсь вызвать HasQueryFilter для этих объектов.

Фильтр должен сравнивать свойство ClientId текущего объекта со свойством службы под названием ITenantProvider.

Вот как я делаю это вручную:

modelBuilder.Entity<MyEntity>().HasQueryFilter(a => a.ClientId == _tenantProvider.TenantId);

К сожалению, метод EF Core HasQueryFilter без Generic занимает LambdaExpression:

public virtual EntityTypeBuilder HasQueryFilter([CanBeNullAttribute] LambdaExpression filter);

Iне знаю, как я могу перевести вышеуказанный вызов в лямбда-выражение.Мой текущий код выглядит следующим образом:

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 голосов
/ 14 декабря 2018

Самый простой способ получить выражение времени выполнения, эквивалентное

_tenantProvider.TenantId

, - это создать лямбда-выражение без параметров времени компиляции и получить его 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);
0 голосов
/ 14 декабря 2018

Предположим, что экземпляр TenantProvider не изменится:

Тогда вместо константного выражения вы можете использовать

Expression.Property(Expression.Constant(_tenantProvider),"TenantId");

Если вы в какой-то момент повторно создадите его, это больше не будет работать.

Предположим, у вас есть статическое свойство, предоставляющее идентификатор tennant, тогда вы можете использовать:

Expression.MakeMemberAccess(null,typeof(TennantIdProvider).GetMember("CurrentId")[0]);
...