【问题标题】:Chaining Lambda expressions链接 Lambda 表达式
【发布时间】:2015-03-24 08:26:29
【问题描述】:

我正在尝试创建代码来过滤可重用和可读的实体框架查询。我下面的代码有效,除非我想加入两个过滤器,如注释掉的部分中所尝试的那样。有没有人能够就如何完成这项工作提供指导和指导?

下面是vs2012在该行时显示的编译时错误信息

//IList<Department> departments3 = context.Set<Department>().Where(isHumanResourcesDepartment || isAccountsDepartment).ToList(); is uncommented

运算符“||”不能应用于类型的操作数 'System.Func ' 和 'System.Func '

    private static void TestCodeReadability2()
    {

        EmployeeDepartmentsConnection context = new EmployeeDepartmentsConnection();

        IList<Department> departments = context.Set<Department>().Where(isAccountsDepartment).ToList();
        IList<Department> departments2 = context.Set<Department>().Where(isHumanResourcesDepartment).ToList();

        //IList<Department> departments3 = context.Set<Department>().Where(isHumanResourcesDepartment || isAccountsDepartment).ToList();

    }


    private static Func<Department, bool> isAccountsDepartment = d=>d.Name.ToLower().Contains("accounts");
    private static Func<Department, bool> isHumanResourcesDepartment = d=>d.Name.ToLower().Contains("human resources");

【问题讨论】:

    标签: c# linq entity-framework linq-to-entities


    【解决方案1】:

    只是补充一下,通过使用 Func,您会强制 EF 从数据库中提取所有数据,然后在本地进行过滤,而不是在数据库上进行过滤。如果要过滤数据库,请将 Func 包装在 Expression 中,方法是将静态方法声明更改为

    Expression<Func<Department, bool>>
    

    【讨论】:

    • 他确实需要这样做,但仅此还不够。
    【解决方案2】:

    为了让 EF 能够将这些查询转换为 SQL 并在数据库方面执行工作,您需要传入 Expression 对象,而不是委托。创建表达式而不是委托非常简单:

    private static Expression<Func<Department, bool>> isAccountsDepartment = 
        d => d.Name.ToLower().Contains("accounts");
    private static Expression<Func<Department, bool>> isHumanResourcesDepartment = 
        d => d.Name.ToLower().Contains("human resources");
    

    接下来,要获取其中任一为真的项目集,您可以使用Union 获取两个查询中任一查询中的所有项目。为了确保这项工作是在数据库而不是在内存中完成的,我们需要从您的内部查询中删除 ToList 调用,以防止它们被加载到内存中:

    private static void TestCodeReadability2()
    {
        EmployeeDepartmentsConnection context = new EmployeeDepartmentsConnection();
    
        var accountsDepartments = context.Set<Department>().Where(isAccountsDepartment);
        var hrDepartments= context.Set<Department>().Where(isHumanResourcesDepartment);
    
        var combined = accountsDepartments.Union(HRDepartments);
    }
    

    【讨论】:

    • 最好的方法不是在this文章的末尾吗? IMO,这种方式是更好的选择。
    • 另外,你不能使用Intersect,而是Union。我说的不对吗?
    • @FarhadJabiyev 这种方法当然可以;他不需要它来完成他在这里描述的事情。能够AndOr 任意表达式当然更强大,但代价是更复杂。
    • Farhad 你提到的那篇文章正是我要找的。​​span>
    猜你喜欢
    • 2019-07-18
    • 1970-01-01
    • 2011-12-13
    • 2012-09-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多