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.AndAlsomultiple times – so if you’ve got individual equality checkse1,e2ande3you might use:One thing to note: you’ll need to use a single
ParameterExpressionfor the whole final expression – so you’ll need to adapt your “build a single check” method to take aParameterExpressionas a parameter… and you don’t need to useExpression.Lambdauntil the very end. So the overall steps will be something like:ParameterExpressionBinaryExpressionusingExpression.Equals, using the sameParameterExpressionyou’ve just created.Expression.AndAlsoExpression.Lambdaat the very end to create anExpression<Func<T, bool>>