C# 扩展方法中的表达式树将在本地计算
我想将租户添加到Asp.Net标识表中(例如:User) 下面的代码段工作正常。租户上下文将通过DI注入,租户将根据http上下文域进行更改: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
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;
};