C# 扩展方法中的表达式树将在本地计算

C# 扩展方法中的表达式树将在本地计算,c#,entity-framework,expression,entity-framework-core,C#,Entity Framework,Expression,Entity Framework Core,我想将租户添加到Asp.Net标识表中(例如:User) 下面的代码段工作正常。租户上下文将通过DI注入,租户将根据http上下文域进行更改: private readonly ITenantContext<ApplicationTenant> tenantContext; public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options, ITenantContext<Appli

我想将租户添加到Asp.Net标识表中(例如: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);
    });
}
private readonly ITenantContext租户上下文;
公共应用程序DBContext(DbContextOptions选项,ITenantContext租户上下文):基本(选项)
{
this.tenantContext=tenantContext;
}
模型创建时受保护的覆盖无效(ModelBuilder)
{
基于模型创建(生成器);
builder.Entity(b=>
{
//添加租户
b、 不动产(类型(int),“租户”);
b、 HasQueryFilter(x=>EF.Property(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);
    }
}
公共静态类EntityTypeBuilderExtensions
{
公共静态无效租赁(
这个EntityTypeBuilder,
表达方式:,
字符串propertyName=“TenantId”)
地点:班级
{
//证实
assure.Argument.NotNull(“builder”,builder);
//向实体添加属性
Property(typeof(int),propertyName.IsRequired();
/*这是可行的,但将在当地进行评估*/
//左
var parameterExp=Expression.Parameter(typeof(tenty),“x”);//e=tenty=>e.g:User
var propertyNameExp=Expression.Constant(propertyName,typeof(string));//租户列的名称-例如:TenantId
//对
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);//表示EF.Property(e,“TenantId”)
var bodyExp=表达式.Equal(propertyMethodExec,tEntantId);
var lambda=Expression.lambda(bodyExp,parameterExp);
建造商HaskeryFilter(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");
    });
}
private Func tenantId=>()=>
{
//返回租户id
if(this.tenantContext!=null&&this.tenantContext.Tenant!=null)
{
返回this.tenantContext.Tenant.Id;
}
返回-1;
};
模型创建时受保护的覆盖无效(ModelBuilder)
{
基于模型创建(生成器);
builder.Entity(b=>
{
b、 AddTenancy(()=>this.tenantId(),“tenantId”);
});
}
扩展方法也可以正常工作,但表达式是在本地计算的:-(。有人能帮我修复它吗

LINQ表达式“where(Property([x],“TenantId”)== 无法转换调用(_ef_filter__tenantId_0)),将被删除 本地计算。LINQ表达式“where([x].NormalizedUserName” ==\uuuuNormalizedUserName\u0)“无法转换,将在本地计算。无法转换LINQ表达式“FirstOrDefault()” 翻译并将在当地进行评估


问题是这里的
Func

private Func<int> tenantId => ...
应该改成

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

    return -1;
};

谢谢Ivan!它可以工作。非常简单…现在看起来还可以。表达式:from:x=>(属性(x,“TenantId”)==Convert(调用(value(ApplicationDbContext.TenantId),Int32))To:x=>(属性(x,“TenantId”)==Convert(value(ApplicationDbContext.TenantId,Int32))
private int tenantId()
{
    // return tenant id
    if (this.tenantContext != null && this.tenantContext.Tenant != null)
    {
        return this.tenantContext.Tenant.Id;
    }

    return -1;
};