2014-04-06 2 views
1

여기에서 얻으려고하는 것에 대한 매우 간단한 코드가 있습니다.EntityFramework : FindBy (열 이름) 표현식 트리로 임의의 열 선택

기본적으로 여기에있는 아이디어는 간단한 FindBy(x => x.<the_column_name>, <the value>);을 수행 할 수 있도록하는 것이므로 열 이름 만 변경하여 동일한 쿼리를 복사하여 붙여 넣을 필요가 없습니다. 지금은 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

말을 LINQ에서 예외가 계속 들어

가능한 일이 있습니까? 아니면 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

당신은 SQL로 번역 할 수있는 엔티티 표현 나무 LINQ를 구성 할 필요가 : 내 머리의 상단에서

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

} 

아직 검증되지 않은.

편집 : 코드가 수정되었습니다.

+1

Hum, 좋은 아이디어이지만'Expression.Equal()'은'BinaryExpression'을 렌더링하고'Where' 메소드는'Func '또는'Expression >'을 필요로하지만 이것을 마음에, 아마도 여기에 할 일이있을 것입니다. – Erick

+0

당신 말이 맞아요. 람다 예측을 잊어 버렸어. 업데이트를 참조하십시오. – user3411327

1

당신이 서명을

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

을 변경하는 경우에는

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

코드는 거의 변화하지 호출 할 수 있습니다,하지만 당신은 표현을 제조 할 필요가 없습니다.

표현식을 SQL로 변환 할 수 있기 때문에 표현식 (Func 아님)을 입력해야합니다. Func은 .Net 대리자로 SQL에 해당하는 것이 없습니다.

+0

실제로 작동하지만, 다시 똑같은 사실에서 쓸모없는 부분을 렌더링합니다. :/ – Erick

+0

글쎄, 아직도'Find' 메소드에'Where'가없는 것을 제외하고는. 이것은 술어를 매개 변수화하는 다소 다른 방법입니다. –