【问题标题】:Often used LINQ returned from method从方法返回的常用 LINQ
【发布时间】:2013-10-07 15:49:20
【问题描述】:

我有 1 个 LINQ,它使用了这么多。我尝试创建返回此 LINQ 的方法,例如:

    public static System.Linq.Expressions.Expression<Func<MyEntity, bool>> GetFilteredEntity() {
        return x => true/*Some condition*/;
    }

    public static Func<MyEntity, bool> GetFilteredEntity() {
        return x => true/*Some condition*/;
    }

然后像这样使用

    db.MyEntities.Where(GetFilteredEntity());

成功了,但是!我需要像这样使用它

    db.ParentEntities.Where(entity => entity.MyEntities.Where(GetFilteredEntity()));

这段代码也编译过,但每次我使用它时,我都会收到错误:

System.InvalidOperationException: There is already an open DataReader associated with this Command which must be closed first.

,甚至:

db.ParentEntities.Where(entity => entity.MyEntities.Where(GetFilteredEntity())).ToList();

也抛出这个异常。

但是,

db.ParentEntities.Where(entity => entity.MyEntities.Where(x => true/*Some condition*/))

仍然可以正常工作! 那么为什么会发生这种情况,并且有办法解决这个问题?

最终工作代码

public static Expression<Func<MyEntity, bool>> GetFilteredEntity() { return x => true/*Some condition*/; }

var expression = GetFilteredEntity();

db.ParentEntities.Where(entity =&gt; entity.MyEntities.AsQueryable().Where(expression ));

也感谢.AsQueryable()Passing func as parameter in Linq to Entities and 'Internal .NET Framework Data Provider error 1025' error

【问题讨论】:

  • 不相关的问题:这应该做什么? db.ParentEntities.Where(entity =&gt; entity.MyEntities.Where(GetFilteredEntity())); ParentEntity 是否派生自 MyEntity
  • Nope =) 它只是将ParentEntity 过滤后的MyEntity 计数大于...(也是问题和答案)

标签: c# linq


【解决方案1】:

在您的第一个示例中,函数在发送到查询提供程序之前被调用并转换为表达式。在接下来的两个示例中,函数调用嵌入在发送到查询提供程序的表达式中,并且该查询提供程序不知道如何处理该函数调用,所以它只是抛出一个异常。当您将实际表达式嵌入到另一个表达式中时,不会有任何函数调用来混淆查询提供程序。

至于解决方案,只需将函数调用拉出到变量中即可。查询提供程序 足够聪明,可以看到您使用了封闭变量,并将提取其值。对于函数调用,它只是不确定是否应该评估它或尝试将其转换为应该在数据库端完成的事情。对于查询提供者和使用它的人来说,尝试两者都做会非常令人困惑且难以使用。为了简化问题,在发送查询之前永远不会执行带有表达式的函数调用。至于闭包变量,没有其他方法可以处理它,因此没有任何其他行为可以混淆它。

var expression = GetFilteredEntity();
db.ParentEntities.Where(entity => entity.MyEntities.Where(expression ));

【讨论】:

    【解决方案2】:

    看起来 LazyLoading 可能是罪魁祸首,您是否尝试过在参数上弹出 ToList()?

    db.ParentEntities.Where(entity => entity.MyEntities.Where(GetFilteredEntity()).ToList());
    

    【讨论】:

    • GetFilteredEntity()表达式 而不是 IQueryable。它没有ToList 方法。
    • 那仍然行不通。这不像您可以在生成查询之前生成一次列表;该列表基于查询中被过滤的实体,因此仍需要将其转换为查询,并且它仍然不知道如何执行此操作。它会因为 OP 的代码中断的完全相同的原因而中断。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多