I have a generic base repository class for LINQ-to-Entities that can do things like selecting an entity based on the ID.
In order to subclass it, you need to implement these two:
protected override Expression<Func<User, bool>> GetByIDSelector(int id)
{
return u => u.UserID == id;
}
protected override Expression<Func<User, int>> KeySelector
{
get { return u => u.UserID; }
}
I would like to just have the KeySelector (which is used for default sort order).
My ‘get by ID’ method looks like this:
public virtual TDataModel GetByID(TKey id)
{
var entity = SetProvider.Set<TDataModel>().Where(GetByIdSelector(id)).SingleOrDefault();
if (entity == null)
{
throw new EntityNotFoundException<TDataModel>(id);
}
return entity;
}
Where GetByIdSelector looks like this, which should turn the KeySelector expression into one that can select by ID.
private Expression<Func<TDataModel, bool>> GetByIdSelector(TKey id)
{
return Expression.Lambda<Func<TDataModel, bool>>
(
Expression.Equal(KeySelector.Body,
Expression.Constant(id)),
KeySelector.Parameters.Single()
);
}
However, the Entity Framework throws an exception that the parameter passed in by that isn’t bound to the query.
The parameter ‘u’ was not bound in the specified LINQ to Entities query expression.
Is there any way I can cleanly reuse the KeySelector Expression without having to rebuild the entire thing?
The reason this doesn’t work is because every time you call
this.KeySelector, it’s creating a brand new lambda expression (hence the call toKeySelector.Parameters.Single()is not the same parameter as the parameter used forKeySelector.Body). Cache that expression into a variable as follows and it will work.What I would probably do is rather fix the code in the KeySelector property to use a fixed value such that the value retrieved is always the same instance.
Example:
Then if you do that – your old code for GetByIdSelector is actually no worse than my version above.