[英]C# Create a LambdaExpression that compares two member properties (for EF Core HasQueryFilter)
我嘗試在OnModelCreating
方法(實體框架核心)中對具有ClientId
屬性(int)的所有實體應用查詢過濾器。 到目前為止,我已經能夠過濾實體,但是我很難為這些實體調用HasQueryFilter。
篩選器應將當前實體的ClientId
屬性與來自名為ITenantProvider
的服務的屬性進行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
進行比較?
獲得等效於運行時表達式的最簡單方法
_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);
假設TenantProvider的實例不變:
然后,可以使用常量表達式代替常量表達式
Expression.Property(Expression.Constant(_tenantProvider),"TenantId");
如果您在某個時候重新實例化,它將不再起作用。
假設您有一些提供tennant id的靜態屬性,則可以使用:
Expression.MakeMemberAccess(null,typeof(TennantIdProvider).GetMember("CurrentId")[0]);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.