2

I'm trying to write a reusable linq expression that I'm passing multiple parameters into:

private System.Linq.Expressions.Expression<Func<FeeDetail, FeeDetail, bool>> IsPrevFeeDetail
   {
       get
       {
           return (feeLevelDetail, currentFeeLevelDetail) =>
           feeLevelDetail.ToDt < currentFeeLevelDetail.FromDt);
       }
   }

But every example of an expression I've seen only takes one parameter (the Entity type that you are querying against).

Is there any way to do this out of the box?

3
  • 5
    the main problem here is that where takes a Func<T, bool> (or an Expression<Func<T,bool>>) - it acts on each row individually, not pairs of rows; the lambda part should be fine, but: where do you intend to use a Func<T,T,bool> ? LINQ-to-SQL doesn't have use for a Func<T,T,bool> as far as I know Commented Mar 21, 2018 at 22:28
  • 1
    I was just about to ask this question. I'm also curious how to do this. My example uses Func<T, int, bool>. The where clause for mine is simpler, I'm checking in the where clause if a column value is 1 or something similar. Commented Mar 21, 2018 at 23:17
  • @MarcGravell yeah I want to use it with LINQ-to-SQL, thats the difficulty... Commented Mar 21, 2018 at 23:37

2 Answers 2

4

Your question at the time of my answer simply asks if Expressions with multiple parameters is possible. They can be used, and are.

.Join and .GroupJoin both have, as a last parameter, an expression parameter that takes types deriving from each side of the join and return a single entity and return a single type.

tableA.Join(tableB, e => e.Id, e => e.TableAId, (a, b) => new {
    IsPrevFee = a.ToDt < b.FromDt,
    AEntry = a,
    BEntry = b
}).Where(e => e.IsPrevFee);

However, judging from the example in your question you seem to want to use it in a Where. That doesn't work because any of the Linq query functions give a collection of a single type as the return. You've seen above I've essentially converted the joining of the 2 entities into a single type of output. I've used an anonymous type but it may be helpful to note that this can also be a concrete type which you can then put in a reusable expression for the join, and then you've got a single-input expression you can pass to a Where clause.

EDIT for comments:

You should be able to create an Expression<Func<MyEntity, bool>> by closing around another argument. I'm doing this on the fly so ignore any trivial syntax errors but an example would be something like this:

Expression<Func<MyEntity, bool>> GetMyWhereClause(int statusId)
{
    return myEntity => myEntity.StatusId == statusId;
}

Usage:

var MyWhereClause = GetMyWhereClause(5);
var result = db.MyEntities.Where(MyWhereClause);

I'm not certain but I don't believe this will work for non-primitives as LINQ-to-SQL may not be able to resolve the resulting expression.

Sign up to request clarification or add additional context in comments.

4 Comments

I think OP and I are asking similar questions, I have a Func<Entity, int, bool> func = (x, y) => x.Property == y;. This to me should also be a very simple where clause in T-SQL that would evaluate to something like where table.Property = 5. How would I go about doing this?
that did work! the problem is that linq to sql can't pick up the value 5 and doesn't generate that sql. I will do some research into creating expression trees. Thank you.
@christopherclark did you get anywhere with your research?
@AntonToshik I came to the conclusion it was a hassle. But it did look like expression trees would work. I just didn't want to have to build out every expression tree. The really weird thing to me was why it was necessary to even build an expression tree. x.Property == y is a normal thing everyone does in their linq-to-sql. So why if i take that out to an expression does it freak out? Another option which I didn't look into was just trying to extend iqueryable, or create a different object that implements iqueryable that would add cross-cutting business detail queries.
0
Expression<Func<T, bool>> filter = q => q.PartitionKey.Equals("1998") 
&& q.RowKey.Equals("Movie-775");

(OR)

Expression<Func<T, bool>> filter = q => q.PartitionKey.Equals("1998");
filter = filter.And(q => q.RowKey.Equals("Movie-775"));

(OR)

IEnumerable<Expression<Func<T, bool>>>? filters; // Collection of expressions.
var filter = filters.First();
filters.Skip(1).ToList().ForEach(x => { filter = filter.And(x); });

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.