EntityFramework:FindBy(列名)按表达式树选择任意列

时间:2014-04-06 20:12:33

标签: c# linq entity-framework entity-framework-6

我有一个非常简单的代码,我想在这里实现。

基本上,这里的想法是能够做一个简单的FindBy(x => x.<the_column_name>, <the value>);,因此我不必通过仅更改列名来复制粘贴相同的查询。

现在我不断从LINQ获得LINQ to Entities does not recognize the method 'System.String Invoke(Spunky.Entities.User)' method, and this method cannot be translated into a store expression

的异常

这可能吗?或者我们还没有使用EF 6.1?

public class UsersRepository
{
  private Lazy<IDataContext> context;

  public UsersRepository()
    : this(() => new DataContext())
  {
  }

  public UsersRepository(Func<IDataContext> context)
  {
    this.context = new Lazy<IDataContext>(context);
  }

  public IQueryable<User> Find(int id)
  {
    return FindBy(u => u.Id, id);
  }

  public IQueryable<User> Find(string username)
  {
    return FindBy(u => u.Username, username);
  }

  public IQueryable<User> FindBy<T>(Func<User, T> property, T value)
  {
    return context.Value
            .Users
            .Where(u => property.Invoke(u).Equals(value));
  }
}

2 个答案:

答案 0 :(得分:1)

如果您更改签名

IQueryable<User> FindBy(Expression<Func<User, bool>> predicate)
{
    return context.Users.Where(predicate);
}

你可以打电话

return FindBy(u => u.Username == username);

代码几乎没有变化,但你不需要制作表达式。

您必须输入表达式(不是Func),因为表达式可以转换为SQL。 Func只是一个.Net委托,没有SQL等价物。

答案 1 :(得分:0)

你需要构造一个表达式linq,实体可以转换为sql:

public IQueryable<T> FindBy<TKey>(Expression<Func<T,TKey>> memberExpression, object value)
{
    var parameterVisitor = new ParameterVisitor(memberExpression);
    var parameter = parameterVisitor.Parameter;
    var constant = Expression.Constant(value);
    var equal = Expression.Equal(memberExpression,constant);
    var predicate = Expression.Lambda(equal, parameter);
    return context.Value.Users.Where(predicate);
}

public class ParameterVisitor : ExpressionVisitor
{
   public ParameterExpression Parameter { get;set;}
   public ParameterVisitor(Expression expr)
   {
       this.Visit(expr);
   }

   protected override VisitParameter(ParameterExpression parameter)
   {
        Parameter = parameter;
        return parameter;
    }

}

仍然没有经过考验。

编辑:修正了代码。