Dynamically build an expression for calling the LINQ Where method
I'm using some code from a book to implement a generic repository class for EF data access. the code uses the following two methods to get a single entity by its int id primary key, assuming all DB objects have an int PK. However, I am using an imported DB with mainly natural keys, and I wish to preserve all the FK relationships as they are, i.e. I don't want to redesign the DB to use single column int PK's.
How can I adapt the code below to work with multi-column keys?
protected Expression<Func<T, bool>> CreateGetExpression<T>开发者_运维技巧;(int id)
{
ParameterExpression e = Expression.Parameter(typeof(T), "e");
PropertyInfo propInfo = typeof(T).GetProperty(KeyPropertyName);
MemberExpression m = Expression.MakeMemberAccess(e, propInfo);
ConstantExpression c = Expression.Constant(id, typeof(int));
BinaryExpression b = Expression.Equal(m, c);
Expression<Func<T, bool>> lambda = Expression.Lambda<Func<T, bool>>(b, e);
return lambda;
}
public override T Get<T>(int id)
{
return List<T>().FirstOrDefault(CreateGetExpression<T>(id));
}
I want my Get method to look like this:
public override T Get<T>(params object[] keyValues)
{
return List<T>().FirstOrDefault(CreateGetExpression<T>(keyValues));
}
Well, you basically need to build up an expression tree with multiple equality checks. You can take the code you've got for building a single equality check, and build up multiple ones, one for each key. Then you need to combine them using Expression.AndAlso multiple times - so if you've got individual equality checks e1, e2 and e3 you might use:
var e = Expression.AndAlso(Expression.AndAlso(e1, e2), e3);
One thing to note: you'll need to use a single ParameterExpression for the whole final expression - so you'll need to adapt your "build a single check" method to take a ParameterExpression as a parameter... and you don't need to use Expression.Lambda until the very end. So the overall steps will be something like:
- Create a
ParameterExpression - For each key, create a
BinaryExpressionusingExpression.Equals, using the sameParameterExpressionyou've just created. - Combine the equality expressions with multiple calls to
Expression.AndAlso - Call
Expression.Lambdaat the very end to create anExpression<Func<T, bool>>
加载中,请稍侯......
精彩评论