我有一个非常简单的代码,我想在这里实现。
基本上,这里的想法是能够做一个简单的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));
}
}
答案 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;
}
}
仍然没有经过考验。
编辑:修正了代码。