gpt4 book ai didi

c# - 扩展方法中的表达式树将在本地进行评估

转载 作者:行者123 更新时间:2023-11-30 12:38:17 32 4
gpt4 key购买 nike

我想将 TenantId 添加到 Asp.Net 身份表(例如:用户)。

以下代码段工作正常。租户上下文将通过 DI 注入(inject),租户根据 http 上下文域进行更改:

private readonly ITenantContext<ApplicationTenant> tenantContext;

public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options, ITenantContext<ApplicationTenant> tenantContext) : base(options)
{
this.tenantContext = tenantContext;
}

protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);

builder.Entity<ApplicationUser>(b =>
{
// add tenant
b.Property(typeof(int), "TenantId");
b.HasQueryFilter(x => EF.Property<int>(x, "TenantId") == this.tenantContext.Tenant.Id);
});
}

为了重用,我想为 entityBuilder 创建一个扩展方法:

public static class EntityTypeBuilderExtensions
{

public static void AddTenancy<TEntity>(
this EntityTypeBuilder<TEntity> builder,
Expression<Func<int>> tenantId,
string propertyName = "TenantId")
where TEntity : class
{
// validate
Ensure.Argument.NotNull("builder", builder);

// add property to entity
builder.Property(typeof(int), propertyName).IsRequired();


/* THIS WORKS BUT WILL BE EVALUATED LOCALLY */
// left
var parameterExp = Expression.Parameter(typeof(TEntity), "x"); // e = TEntity => e.g: User
var propertyNameExp = Expression.Constant(propertyName, typeof(string)); // the name of the tenant column - eg.: TenantId
// right
var tTenantId = Expression.Convert(tenantId.Body, typeof(int)); // tenantId
var propertyMethod = typeof(EF).GetMethod(nameof(EF.Property), BindingFlags.Public | BindingFlags.Static).MakeGenericMethod(typeof(int)); // build EF.Property
var propertyMethodExec = Expression.Call(propertyMethod, parameterExp, propertyNameExp); // represents EF.Property(e, "TenantId")
var bodyExp = Expression.Equal(propertyMethodExec, tTenantId);
var lambda = Expression.Lambda(bodyExp, parameterExp);
builder.HasQueryFilter(lambda);
}
}

在数据库上下文中:

private Func<int> tenantId => () =>
{
// return tenant id
if (this.tenantContext != null && this.tenantContext.Tenant != null)
{
return this.tenantContext.Tenant.Id;
}

return -1;
};

protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);

builder.Entity<ApplicationUser>(b =>
{
b.AddTenancy(() => this.tenantId(), "TenantId");
});
}

扩展方法也可以正常工作,但表达式是在本地计算的:-(。有人可以帮我解决这个问题吗?

The LINQ expression 'where (Property([x], "TenantId") == Invoke(__ef_filter__tenantId_0))' could not be translated and will be evaluated locally. The LINQ expression 'where ([x].NormalizedUserName == __normalizedUserName_0)' could not be translated and will be evaluated locally. The LINQ expression 'FirstOrDefault()' could not be translated and will be evaluated locally.

最佳答案

问题是这里的Func

private Func<int> tenantId => ...

这会导致错误的翻译 Invoke(__ef_filter__tenantId_0)) 和客户评估。

解决方案是使 tenantId 简单 int 返回属性或方法。例如,保持通话

b.AddTenancy(() => this.tenantId(), "TenantId");

应该改为

private int tenantId()
{
// return tenant id
if (this.tenantContext != null && this.tenantContext.Tenant != null)
{
return this.tenantContext.Tenant.Id;
}

return -1;
};

关于c# - 扩展方法中的表达式树将在本地进行评估,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53839690/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com