2

I have 1 LINQ which used so much. I try create the method which return this LINQ like:

    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*/;
    }

And use this like

    db.MyEntities.Where(GetFilteredEntity());

is successfull, But! I need use it like

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

This code compiled too, but every time when i use it, i got the Error:

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

,even:

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

throw this Exception too.

But,

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

still works fine! So why it happend, and have some way to get round this?

Final working code

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

and

var expression = GetFilteredEntity();

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

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

Community
  • 1
  • 1
Anton
  • 45
  • 4
  • Unrelated question: What is this supposed to do? `db.ParentEntities.Where(entity => entity.MyEntities.Where(GetFilteredEntity()));` Does `ParentEntity` derive from `MyEntity`? – Khan Oct 07 '13 at 16:19
  • Nope =) It's Just taking `ParentEntity` where filtered count of `MyEntity` bigger than... (Also it Question and Answers) – Anton Oct 08 '13 at 09:33

2 Answers2

4

In your first example the function is called and translated into an expression before it is even sent to the query provider. In the next two examples the function call is embedded within an expression that is sent to the query provider, and that query provider doesn't know what to do with that function call, so it just throws an exception. When you embed the actual expression in another expression, there is no function call to confuse the query provider.

As for a solution, just pull out the function call into a variable. The query provider is smart enough to see that you used a closed over variable, and will pull out its value. For a function call it's just not sure if it should evaluate it or try to translate it into something that should be done on the DB's end. Trying to do some of both would just be very confusing and hard to work with, both for the query provider, and for people using it. To simplify matters, function calls with expressions are never executed prior to sending the query. As for a closed over variable, there is no other way that it could be treated, so there isn't any other behavior to confuse it with.

var expression = GetFilteredEntity();
db.ParentEntities.Where(entity => entity.MyEntities.Where(expression ));
Servy
  • 202,030
  • 26
  • 332
  • 449
-1

Looks like LazyLoading might be the culprit, have you tried popping the ToList() on the parameters?

db.ParentEntities.Where(entity => entity.MyEntities.Where(GetFilteredEntity()).ToList());
openshac
  • 4,966
  • 5
  • 46
  • 77
  • `GetFilteredEntity()` is an *expression* not an `IQueryable`. It doesn't have a `ToList` method. – Servy Oct 07 '13 at 16:01
  • That still won't work. It's not like you can generate the list once before the query is generated; the list is based on the entity being filtered on in the query, so it's still needing to be translated into a query, and it still doesn't know how to do that. It'll break for the exact same reason the OP's code breaks. – Servy Oct 07 '13 at 16:11