views:

48

answers:

3

I have this method:

public static Expression<Func<MyEntity, bool>> MyMethod(string someId)
    {
        return o => o.SomeProperty.Equals(someId);
    }

This is being passed to another method that uses entity framework with this expression to retrieve the matching items. My problem is it doesn't work. If I replace the someId as part of the Equals call with an actual value it works. However, it doesn't work if I pass the same value into this method above.

Does this mean the someId parameter doesn't get evaluated until the expression is actually used and therefore doesn't contain the actual value? Sorry, getting a bit confused here.

Thanks

Update:

Some debug info for the one that DOES work where the param is hard coded

.Lambda #Lambda1<System.Func`2[MyEntity,System.Boolean]>(MyEntity $t) {\r\n    .Call ($t.SomeProperty).Equals(\"test1\")

Some debug info for the one that DOES NOT work where the value is passed into the method

.Lambda #Lambda1<System.Func`2[MyEntity,System.Boolean]>(MyEntity $t) {\r\n    .Call ($t.SomeProperty).Equals(.Constant<MyEntity+<>c__DisplayClass4>(MyEntity+<>c__DisplayClass4).someId)

I am guessing when the value is not hard coded the expression has got a reference to something that doesn't exist? Sorry, getting myself in a muddle with what is going on here!

Update 2:

This is where it is being used - a method in a repository class:

public MyEntity Get(string someId)
{
   var queryPredicate = MyEntity.MyMethod(someId);
   var foundEntity = this.Query(queryPredicate);
}

Query is a method on the repository base class as below:

public IEnumerable<TEntity> Query(Expression<Func<TEntity, bool>> predicate)
{
    if (predicate == null)
    {
        throw new ArgumentNullException("predicate");
    }
    using (var context = new TContext())
    {
        return context.CreateObjectSet<TEntity>().AsExpandable().Where(predicate).ToList();
    }
}
A: 

Are you sure that the given value is not null? Can you give the exception it throws? Maybe it's a "int" that you need to pass as a ID?

Sylvain Perron
There isn't an exception, it just doesn't match anything when using the expression.
Jon Archway
Are you sure your code is using that expression?Put a breakpoint at the return line and when you're on it try to use Quickwatch to find the right way to use it by replacing what you use as a value.
Sylvain Perron
100% sure it is using it both times.
Jon Archway
Looking at the debug:.Lambda #Lambda1<System.Func`2[MyEntity,System.Boolean]>(MyEntity $t) {\r\n .Call ($t.SomeProperty).Equals(\"test1\").Lambda #Lambda1<System.Func`2[MyEntity,System.Boolean]>(MyEntity $t) {\r\n .Call ($t.SomeProperty).Equals(.Constant<MyEntity+<>c__DisplayClass4>(MyEntity+<>c__DisplayClass4).someId)The first one works, which is where the value is hard coded. The second one doesn't where the method is using the passed param. I am assuming when the expression is used it hasn't got the actual param at this point for the second one which is why it doesn't work??
Jon Archway
A: 

I don't have a compile hnady to test this, but from the IL code, it seems to be create a closure for someId. Basically, it's creating a func/expression which will be compiled & executed later, and the compile assumes that you'll want the value of someId at the time it's run, rather than at the time the expression was created. I think if you pass it through a temp, it should work.

public static Expression<Func<MyEntity, bool>> MyMethod(string someId) 
{ 
    string tempSomeId = someId;
    return o => o.SomeProperty.Equals(tempSomeId); 
} 
James Curran
Thanks, that's kind of what I had been thinking. However, the above still doesn't work unfortunately.
Jon Archway
+1  A: 

This sounds like a problem where LinqKit can be the solution you are looking for:

http://www.albahari.com/nutshell/linqkit.aspx

Have a look at it and see if it solves it :)

wasatz
That is what I am using, hence the "AsExpandable" in the example above. Thanks for the suggestion though. Any other ideas what I am doing wrong?
Jon Archway
Argh! I have found the problem and it is due to the string in the database containing spaces after the characters therefore "Equals" didn't work. Argh! Argh! Argh! Thanks for your help anyway :-)
Jon Archway