加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

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

发布时间:2020-12-15 22:54:35 所属栏目:百科 来源:网络整理
导读:我想将TenantId添加到Asp.Net Identity表(例如:User). 以下代码段正常.租户上下文将通过DI注入,租户根据http上下文域进行更改: private readonly ITenantContextApplicationTenant tenantContext;public ApplicationDbContext(DbContextOptionsApplication
我想将TenantId添加到Asp.Net Identity表(例如:User).

以下代码段正常.租户上下文将通过DI注入,租户根据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);
    }
}

并在db上下文中:

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 => ...

这导致错误的翻译调用(__ 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;
};

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读