2013-08-02 2 views
1

검색 매개 변수 세트에서 전달하는 데이터 계층에 LINQKit의 PredicateBuilder 클래스를 사용하여 필요한 'where'절을 동적으로 작성한 다음이를 반환하도록 LINQ 쿼리를 실행하는 메서드가 있습니다. 개체 목록.동적으로 LINQ 조인 추가

경우에 따라 검색 조건에 라이브러리 테이블에 존재하지 않는 카테고리 이름이 포함되어있을 수 있으므로 필요한 쿼리를 수행하기 위해이 테이블에 가입해야합니다. 이 방법을 사용한 이유는 책 당 잠재적으로 수백 가지 카테고리가 있기 때문이며 최적화를 위해 실제로 필요한 경우 조인을 수행하기를 원합니다.

내 질문은, 동적으로 LINQ 쿼리에이 조인을 추가 할 수 있습니까?

이 기능을 작동시키려는 몇 가지 시도 후에 불행히도 '컷 앤 페이스트'패턴에 의존해야만했습니다.이 패턴은 제가 대단히 싫어하기는하지만 '아웃 - 더 - 문'.

아래의 코드는 내가 현재 가지고 무슨 이름이 변수 추출물 (이 정말 라이브러리 응용 프로그램이 아닙니다 즉!) :

public IEnumerable<ILibrarySearchResultsDTO> SearchLibrary(ISearchLibrary searchValues) 
{ 
    var whereStatement = PredicateBuilder.True<Library>(); 

    bool categorySearch = false; 

    if (!string.IsNullOrEmpty(searchValues.AuthorFirstName)) 
     whereStatement = whereStatement.And(q => q.AuthorFirstName == searchValues.AuthorFirstName); 

    if (!string.IsNullOrEmpty(searchValues.AuthorLastName)) 
     whereStatement = whereStatement.And(q => q.AuthorLastName == searchValues.AuthorLastName); 

    if (!string.IsNullOrEmpty(searchValues.CategoryName)) 
     categorySearch = true; 

    var libraryObjectSet = Context.CreateObjectSet<Library>(); 
    LibraryObjectSet.MergeOption = MergeOption.NoTracking; 

    var categoriesObjectSet = Context.CreateObjectSet<Categories>(); 
    categoriesObjectSet.MergeOption = MergeOption.NoTracking; 

    if (!categorySearch) 
    { 
     var query = from lib in libraryObjectSet 
        .Where(whereStatement) 
        .Take(ConfigHelper.MaxQueryRecords) 
        .AsExpandable() 
        select new LibrarySearchResultsDTO() 
        { 
         BookName = lib.BookName, 
         AuthorFirstName = lib.AuthorFirstName, 
         AuthorLastName = lib.AuthorLastName, 
         ISBN = lib.ISBN 
        }; 
    } 
    else 
    { 
     var query = from lib in LibraryObjectSet 
        .Where(whereStatement) 
        .Take(ConfigHelper.MaxQueryRecords) 
        .AsExpandable() 
        join categories_LKP in categoriesObjectSet on new { CategoryID = lib.CategoryID, CategoryName = searchValues.CategoryName } 
         equals new { CategoryID = categories_LKP.CategoryID, CategoryName = categories_LKP.CategoryName } 
        select new LibrarySearchResultsDTO() 
        { 
         BookName = lib.BookName, 
         AuthorFirstName = lib.AuthorFirstName, 
         AuthorLastName = lib.AuthorLastName, 
         ISBN = lib.ISBN 
        };  
    } 

    return query.ToList(); 
} 

난에 나와있는 예제 코드를 작성 했어 메모장 + + 및 인위적인 예를 들어 있기 때문에 내가 컴파일 된 경우 확인할 수 없습니다. 해야한다 (나는 희망한다!). 당신은 알 수없는 유형의 동적 쿼리를 컴파일하기의 일반적인 기능 ... 같은 반사 API를 사용할 수 있습니다

답변

1

Category-Library에서 탐색 속성은 그냥 동적으로 할 수있는 경우 다른 조건을 추가 탐색 속성이없는 경우

if (!string.IsNullOrEmpty(searchValues.CategoryName)) 
{ 
    whereStatement = whereStatement 
        .And(q => q.Categories 
         .Any(c => c.CategoryName == searchValues.CategoryName)); 
} 

, 당신은 여전히 ​​전체 쿼리를 복제 할 필요없이 술어에 참여 사용할 수 있습니다. 그러나 탐색 속성을 추가하는 것이 좋은 이유 일 수 있습니다.

+0

도움을 주셔서 감사합니다. 'Contains'즉 var categoryQuery = categoriesObjectSet의 x에서 WHERE 문에 하위 쿼리를 추가하는 결과가 나타납니다. 여기서 x.CategoryName == searchValues.CategoryName select x.CategoryID; whereStatement = whereStatement.Add (q => categoryQuery.Contains (q.CategoryID); – Damon

0

...

IQueryable<T> getQuery<T>(T myTableEntity, string[] arrayOfQueryTerms, Expression<Func<T, bool>> predicate) 
{ 
    var fieldOrProperty = getMemberInfo(predicate); 
} 

MemberInfo getmemberInfo<T>(Expression<Func<T,bool> expr) 
{ 
    var memberExpr = expr as MemberExpression; 
    if (memberExpr != null) return memberExpr.Member; 
     throw new ArgumentException(); 
} 

var q = getQuery<FooTable>(foo, new[]{"Bar","Baz"}, x=>x.FieldName);