我正在使用书中的一些代码来实现EF数据访问的通用存储库类。假设所有DB对象都具有int PK,代码使用以下两种方法通过其int id
主键获取单个实体。但是,我使用的是主要是自然键的导入数据库,我希望保留所有FK关系,即我不想重新设计数据库以使用单列int PK。
如何调整以下代码以使用多列密钥?
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));
}
我希望我的Get
方法看起来像这样:
public override T Get<T>(params object[] keyValues)
{
return List<T>().FirstOrDefault(CreateGetExpression<T>(keyValues));
}
答案 0 :(得分:1)
好吧,你基本上需要构建一个带有多个相等性检查的表达式树。您可以获取用于构建单个相等性检查的代码,并构建多个代码,每个密钥对应一个。然后,您需要多次使用Expression.AndAlso
将它们组合在一起 - 因此,如果您有个别等式检查e1
,e2
和e3
,则可以使用:
var e = Expression.AndAlso(Expression.AndAlso(e1, e2), e3);
有一点需要注意:您需要使用单 ParameterExpression
作为整个最终表达式 - 所以您需要调整“构建单一检查”方法将ParameterExpression
作为参数...并且在最后之前不需要使用Expression.Lambda
。所以整体步骤将是:
ParameterExpression
BinaryExpression
创建Expression.Equals
,使用您刚刚创建的ParameterExpression
。Expression.AndAlso
Expression.Lambda
以创建Expression<Func<T, bool>>