在实体框架拦截器中向 DbScanExpression 添加内部联接

2024-05-15

我正在尝试使用实体框架 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?或者我还缺少其他东西吗?


您获得该异常的原因是因为 InnerJoin 生成两个表中列的组合结果,另一方面查询应该返回 User 类的那些匹配属性,因此您还需要在查询末尾使用投影。这是对我有用的代码:

public override DbExpression Visit(DbScanExpression expression)
{
    var table = expression.Target.ElementType as EntityType;
    if (table != null && table.Name == "User")
    {
        return expression.InnerJoin(
            DbExpressionBuilder.Scan(expression.Target.EntityContainer.BaseEntitySets.Single(s => s.Name == "TennantUser")),
            (l, r) =>
                DbExpressionBuilder.Equal(
                    DbExpressionBuilder.Property(l, "UserId"),
                    DbExpressionBuilder.Property(r, "UserId")
                )
        )
        .Select(exp => 
            new { 
                UserId = exp.Property("l").Property("UserId"), 
                Email = exp.Property("l").Property("Email") 
            });
    }

    return base.Visit(expression);
}

正如您在连接操作后所看到的,您可以通过使用指定连接条件的表达式中的 lambda 表达式别名来引用特定的连接表。因此,在我的例子中,您将 User 表称为 l,将 TennantUser 称为 r。在发送到数据库的 SQL 查询结果中将使用字母 l 和 r 以及别名。在 InnerJoin 和 Select 操作之间,您可以放置​​所需的其他逻辑,例如 Filter 等。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在实体框架拦截器中向 DbScanExpression 添加内部联接 的相关文章

随机推荐

  • D3 v4 在同一元素上进行画笔和缩放(鼠标事件不冲突)

    我的目标是构建一个使用两者的 D3 v4 图表d3 zoom https github com d3 d3 zoom and d3 brush https github com d3 d3 brush一起 如下 当鼠标位于 x 轴上时 用户
  • 关闭 css 、 vue cli 3 webpack 4 的单独块

    我正在使用使用最新版本的 vue cli 3 创建的项目 我使用的是默认配置 我的路由器有很多动态导入的路由 我的 css 和 js 在生产环境中运行时都被分成多个块 虽然 js 的行为是可取的 我的 css 文件非常小 我想关闭 css
  • Strapi 未加载 Digital Ocean 上托管的现有 MongoDB 中的集合

    我正在使用 Strapi 创建一个新应用程序 并尝试将其与托管在 Digital Ocean 上的 MongoDB 连接 但不幸的是Strapi 无法从现有 MongoDB 获取集合 在这里 我提到我实现 Strapi 与现有 MongoD
  • 如何在 Spring 中使 @PropertyResource 优先于任何其他 application.properties ?

    我正在尝试在类路径之外添加外部配置属性资源 它应该覆盖任何现有的属性 但以下方法不起作用 SpringBootApplication PropertySource d app properties public class MyClass
  • Android 无法解析日期异常

    当尝试解析发送到我的 Android 客户端的日期字符串时 我得到一个无法解析的日期 这是例外 java text ParseException 无法解析的日期 2018 09 18T00 00 00Z 位于 偏移量 19 在 java t
  • MS Access 执行 POST Web 请求

    在我的 MS Access 应用程序中 我需要定期向我的网络服务器发送一批信息 我不需要任何花哨的东西 比如 SOAP XML RPC 或任何东西 只需一个简单的 POST 页面请求就足够了 我用谷歌搜索了一下 但找不到任何真正有用的东西
  • arm-linux-gnueabi 编译器选项

    我在用 ARM Linux gnueabi gcc在 Linux 中为 ARM 处理器编译 C 程序 但是 我不确定它编译的默认 ARM 模式是什么 例如 对于 C 代码 test c unsigned int main return 0x
  • 在 C/C++ 中获得正模数的最快方法

    通常在我的内部循环中 我需要以 环绕 方式索引数组 因此 例如 如果数组大小为 100 并且我的代码要求元素 2 则应该给它元素 98 高级语言 例如 Python 可以简单地使用my array index array size 但由于某
  • 如何在java中将日期格式从YYMMDD更改为YYYY-MM-DD? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我从机器可读代码中获取日期格式为 YYMMDD 如何将其更改为 YYYY MM DD 例如我收到 871223 YYMMDD 我想把它改成
  • QToolButton:更改菜单位置

    使用菜单时QToolButton菜单显示在按钮的正下方 有没有办法在按钮的左侧 右侧显示菜单 我知道这个问题不久前已得到回答 但我想为此问题添加新答案 因为接受的答案不再有效 实际上 更改 QToolButton 上的菜单位置非常容易 您需
  • Sun 在 EDT 之外做 GUI 工作的演示?

    我正在看SplashDemo java http download oracle com javase tutorial uiswing examples misc SplashDemoProject src misc SplashDemo
  • MVC + Razor:如何有条件地添加起始

    我想根据变量是否设置来修改div 所以我想做这样的事情 if SomethingIsSet div style background red else div style background blue 但我在 Visual Studio
  • 有没有快速创建集合的方法?

    目前我正在创建一个像这样的新集 std set a s s insert a1 s insert a2 s insert a3 s insert a10 有没有办法创建s在一行 int myints 10 20 30 40 50 std s
  • Laravel Schema Builder 改变存储引擎

    我正在尝试更改表并将其存储引擎更改为InnoDb 当我跑步时php artisan migrate它完成且没有错误 然而 当我检查 Sequel Pro 中的存储引擎时 没有任何变化 public function up Schema ta
  • Excel VBA 过滤和复制粘贴数据

    给定一个数据集 假设有 10 列 在 A 列中我有日期 在 B 列中我有 我想仅过滤 A 列 2014 年的数据 B 列 ActiveSheet Range A 1 AR 1617 AutoFilter Field 5 Operator x
  • 如何在 Swift Playgrounds 中获得弹出对话框

    我想知道如何在 Swift 中弹出一个对话框游乐场 是的 必须在 Playgrounds 中 我尝试了以下代码 直接来自 AppleDevs 站点 然而 无论我如何尝试 self tag always抛出错误 谁能帮我这个 import U
  • 如何在字段值无效的情况下更改 Struts2 验证错误消息?

    我在 Web 表单上使用 Struts2 验证 如果字段假设为整数或日期 则
  • QCombobox 向下箭头图像

    如何更改Qcombobox向下箭头图像 现在我正在使用这个 QSS 代码 但这不起作用 我无法删除向下箭头边框 QComboBox border 0px QComboBox down arrow border 0px background
  • 如何在 Haskell 中漂亮地打印表格?

    我想在 Haskell 中漂亮地打印一个类似表格的数据结构 列列表 例如 Table StrCol strings a bc c IntCol ints 1 30 2 DblCol doubles 2 0 4 5 3 2 应该渲染类似 st
  • 在实体框架拦截器中向 DbScanExpression 添加内部联接

    我正在尝试使用实体框架 CommandTree 拦截器通过 DbContext 向每个查询添加过滤器 为了简单起见 我有两个表 一个称为 User 有两列 UserId 和 EmailAddress 另一个称为 TenantUser 有两列