c# - 表达式 : a get-by-ID-selector when I have the Expression to get the ID?

标签 c# linq-to-entities expression-trees

我有一个用于 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 获取”方法如下所示:

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()
  );
}

但是, Entity Framework 抛出一个异常,即传入的参数未绑定(bind)到查询。

The parameter 'u' was not bound in the specified LINQ to Entities query expression.

有什么方法可以干净地重用 KeySelector 表达式而不必重建整个东西?

最佳答案

这不起作用的原因是因为每次调用 this.KeySelector 时,它都会创建一个全新的 lambda 表达式(因此调用 KeySelector.Parameters.Single() 与用于 KeySelector.Body 的参数不同)。将该表达式缓存到一个变量中,如下所示,它将起作用。

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()
    );
}

我可能会做的是修复 KeySelector 属性中的代码以使用固定值,以便检索到的值始终是相同的实例。

例子:

private static readonly Expression<Func<User, int>> _keySelector = u => u.UserID;

protected override Expression<Func<User, int>> KeySelector
{
    get { return _keySelector; }
}

那么如果您这样做 - 您的 GetByIdSelector 旧代码实际上并不比我上面的版本差。

关于c# - 表达式 : a get-by-ID-selector when I have the Expression to get the ID?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5067833/

相关文章:

c# - 将只读属性分配给 Entity Framework 中的新对象

c# - 为什么索引一维数组的实例是 BinaryExpression 而不是 MethodCallExpression?

c# - Expression.Block() 可以在 lambda 闭包中返回一个值吗?

prolog - 在 Prolog 中构建表达式树

c# - 我怎样才能从html中提取文本

c# - 无效操作异常 : This operation cannot be performed while an auto-filled column is being resized

c# - 从字符串转换为 <T>

linq-to-entities - LINQ to Entities 无法识别 ElementAt[WebSecurity.CurrentUserId] 方法

c# - ASP.NET - 在 RenderContent 调用中将事件处理程序添加到 Repeater 内的 LinkBut​​ton

c# - LINQ 中的条件 WHERE