我正在尝试使用实体框架 CommandTree 拦截器通过 DbContext 向每个查询添加过滤器。
为了简单起见,我有两个表,一个称为“User”,有两列(“UserId”和“EmailAddress”),另一个称为“TenantUser”,有两列(“UserId”和“TenantId”)。
每次对 User 表进行 DbScan 时,我都想对 TenantUser 表进行内部联接,并根据 TenantId 列进行过滤。
有一个项目叫EntityFramework.Filters https://github.com/jbogard/EntityFramework.Filters它沿着这些思路做了一些事情,但不支持“复杂连接”,这似乎是我想要做的。
下列的TechEd 2014 的演示 http://channel9.msdn.com/Events/TechEd/NorthAmerica/2014/DEV-B417,我创建了一个拦截器,它使用访问者并使用以下方法将 DbScanExpressions 替换为 DbJoinExpression。一旦我开始工作,我计划将其包装在 DbFilterExpression 中,以将 TenantId 列与已知 ID 进行比较。
public override DbExpression Visit(DbScanExpression expression)
{
var table = expression.Target.ElementType as EntityType;
if (table != null && table.Name == "User")
{
return DbExpressionBuilder.InnerJoin(expression, DbExpressionBuilder.Scan(expression.Target), (l, r) =>
DbExpressionBuilder.Equal(DbExpressionBuilder.Variable(tenantUserIdProperty.TypeUsage, "UserId"),
DbExpressionBuilder.Variable(userIdProperty.TypeUsage, "UserId")));
}
return base.Visit(expression);
}
为了测试上面的代码,我将拦截器添加到 dbContext 并运行以下代码:
dbContext.Users.Select(u => new { u.EmailAddress }).ToList();
但是,这会导致以下错误:
类型 'Transient.rowtype[(l,CodeFirstDatabaseSchema.User(Nullable=True,DefaultValue=)),(r,CodeFirstDatabaseSchema.User(Nullable=True,DefaultValue=))] 没有声明名称为 'EmailAddress' 的属性'。
我是否错误地构建了 DbJoinExpression?或者我还缺少其他东西吗?