我有一个LINQ-to-Entities的通用基础存储库类,可以执行基于ID选择实体的操作。
为了对其进行子类化,您需要实现这两个:
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; }
}
我想要KeySelector
(用于默认排序顺序)。
我的'ID by ID'方法如下所示:
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;
}
GetByIdSelector
看起来像这样,应该将KeySelector
表达式转换为可以按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()
);
}
但是,实体框架会抛出一个异常,即传入的参数未绑定到查询。
参数“u”未绑定在指定的LINQ to Entities查询表达式中。
有没有什么方法可以干净地重用KeySelector
表达式而无需重建整个事物?
答案 0 :(得分:3)
这不起作用的原因是因为每次调用this.KeySelector
时,它都会创建一个全新的lambda表达式(因此对KeySelector.Parameters.Single()
的调用与用于{的参数不同。 {1}})。将该表达式缓存到变量中,如下所示,它将起作用。
KeySelector.Body
我可能会做的是修复KeySelector属性中的代码以使用固定值,以便检索的值始终是相同的实例。
示例:
private Expression<Func<TDataModel, bool>> GetByIdSelector(TKey id)
{
var keySelector = KeySelector;
return Expression.Lambda<Func<TDataModel, bool>>(
Expression.Equal(
keySelector.Body,
Expression.Constant(id)
),
keySelector.Parameters.Single()
);
}
然后,如果你这样做 - 你的旧代码GetByIdSelector实际上并不比我上面的版本差。