2010-04-20 1 views
1

내 서투른 설명을 용서,하지만 난 목록을 포함하는 클래스가 있습니다 List <T>을 속성으로 사용하여 개체를 쿼리하는 식 트리를 생성하려면 어떻게해야합니까?

public class Document 
    { 
     public int OwnerId { get; set; } 
     public List<User> Users { get; set; } 

     public Document() { } 
    } 

    public class User 
    { 
     public string UserName { get; set; } 
     public string Department { get; set; } 
    } 

은 현재 내가 내 개체에 동적 쿼리를 수행 할 PredicateBuilder를 사용합니다. 내가 식 트리에 다음 LINQ 문을 설정할 수 있습니다 방법 : 즉 var deptDocs = documents.HasUserAttributes("Department", "HR").ToList();에서

var predicate= PredicateBuilder.True<User>(); 
predicate= predicate.And<User>(user => user.Deparment == "HR"); 

var deptDocs = documents.AsQueryable() 
      .Where(doc => doc.Users 
      .AsQueryable().Count(predicate) > 0) 
      .ToList(); 

. 내가 말할 수있는 것부터, Expression.Invoke를 발행 할 경우 내 문제로 user => user.Deparment == "HR" 행을 평가할 수 없습니다.

UPDATE :

var predicate = PredicateBuilder.True<User>(); 
predicate = predicate.And<User>(user => user.Department == "FIN"); 

Expression<Func<Document, bool>> userSelector = 
      doc => doc.Users 
      .AsQueryable() 
      .Any(predicate); 

var docParm = Expression.Parameter(typeof(Document), "appDoc"); 
var body = Expression.Invoke(userSelector, docParm); 
var lambda = Expression.Lambda<Func<Document, bool>>(body, docParm); 

var allPredicate = PredicateBuilder.True<Document>();    
allPredicate = allPredicate.And<Document>(doc => doc.OwnerId == 1); 
allPredicate = allPredicate.And<Document>(lambda); 

var hrDocs = this.docs.AsQueryable().Where(allPredicate).ToList(); 

이 할 수있는보다 효과적인 방법이 있나요 : 나는이에 대한 몇 가지 진전을 생각

? 어떻게 predicate - user => user.Department - generics를 생성하는 표현식을 만들 수 있습니까?

답변

0

나는 다음과 같은 구문으로 쿼리를 수행 할 수있는 어느 정도 만족스러운 해결책을 마련했습니다

var predicate = PredicateBuilder.True<Document>(); 
predicate = predicate.And<Document>(User.SubQuery("UserName", "DAVER")); 
predicate = predicate.And<Document>(AdHoc<Document>("OwnerId", 1)); 

var finDocs = docs.AsQueryable().Where(predicate).ToList(); 

나는이 방법으로 확장 클래스가 있습니다

public static Expression<Func<T, bool>> AdHoc<T> 
      (string columnName, object compValue) 
{ 
    // Determine type of parameter 
    ParameterExpression parameter = Expression.Parameter(typeof(T), "x"); 
    // Target to compare to 
    Expression property = Expression.Property(parameter, columnName); 
    // The value to match 
    Expression constant = Expression.Constant(compValue, compValue.GetType()); 

    Expression equality = Expression.Equal(property, constant); 
    Expression<Func<T, bool>> predicate = 
    Expression.Lambda<Func<T, bool>>(equality, parameter); 

    return predicate; 
} 

그리고에를 내 사용자 클래스 나는 정적 메서드가 있습니다 :

public static Expression<Func<Document, bool>> SubQuery(string property, 
                 string targetValue) 
     { 
      var predicate = PredicateBuilder.True<User>(); 
      predicate = predicate.And<User>(Extensions.AdHoc<User>(property, targetValue)); 

      Expression<Func<Document, bool>> userSelector = 
            doc => doc.Users 
             .AsQueryable() 
             .Any(predicate); 

      var docParm = Expression.Parameter(typeof(Document), "appDoc"); 
      var body = Expression.Invoke(userSelector, docParm); 

      var docPredicate = PredicateBuilder.True<Document>(); 
      docPredicate = docPredicate.And<Document>(Expression.Lambda<Func<Document, bool>>(body, docParm)); 

      return docPredicate; 
     } 

단점은 내가 포함 된 정적입니다 User 클래스 자체의 uery 기능 그것은 일을 끝내지 만, 제네릭을 사용하는 제안이나 더 나은 방법이 있다면 누구든지 내 정적 클래스를 사용자 클래스에 포함시킬 필요가 없다. 나는 당신이해야 할 말을 듣고 싶어한다.

0

원하는 것을 얻으시겠습니까 this toolkit?

+0

흥미 롭습니다 - 게시물을 이해하면 미리 검색어를 등록 하시겠습니까? 이 접근 방식을 사용 했습니까? –

+0

오른쪽; 컴파일하기 전에 쿼리를 빌드해야합니다. 저는이 접근법을 정신으로 사용했지만이 특정 툴킷으로는 사용하지 않았습니다. –