2013-08-02 61 views
1

我在我在其中通过在一组搜索参数我的数据层的方法,动态地使用从LINQKit所述PredicateBuilder类建立所需的“其中”子句,然后执行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(); 
} 

我已经在创建示例代码记事本+ +,因为这是一个人为的例子,我一直无法检查它是否编译。应该尽管(我希望!)。

回答

1

如果从Library导航属性Category你可以动态添加另一个谓词:

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

如果导航属性不存在,您仍然可以使用于断言无需复制整个查询的联接。但是,添加导航属性可能是一个很好的理由。

+0

感谢您的帮助,最终通过附加子查询的WHERE语句“包含”即VAR categoryQuery从X在categoriesObjectSet =其中x.CategoryName == searchValues.CategoryName选择x.CategoryID; whereStatement = whereStatement.Add(q => categoryQuery.Contains(q.CategoryID); – Damon

0

你可以使用反射API像下面的泛型函数...这编译一个未知类型动态查询...

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