动态附加LINQ Join
本文关键字:Join LINQ 动态 | 更新日期: 2023-09-27 18:26:09
我在数据层中有一个方法,我在其中传递一组搜索参数,使用LINQKit中的PredicateBuilder类动态构建所需的'where'子句,然后执行LINQ查询以返回对象列表。
在某些情况下,搜索条件可能包含Library表中不存在的类别名称,然后我需要加入该表以执行必要的查询。之所以这样做,是因为每本书可能有数百个类别,出于优化原因,我只希望在实际需要时执行连接。
现在我的问题是,是否可以将这个联接动态地附加到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();
}
我不得不在Notepad++中创建示例代码,因为这是一个人为的示例,所以我无法检查它是否编译。应该这样做(我希望!)。
如果有从Library
到Category
的导航属性,您可以动态添加另一个谓词:
if (!string.IsNullOrEmpty(searchValues.CategoryName))
{
whereStatement = whereStatement
.And(q => q.Categories
.Any(c => c.CategoryName == searchValues.CategoryName));
}
如果导航属性不存在,则仍然可以在谓词中使用联接,而不必复制整个查询。但这可能是添加导航属性的一个很好的理由。
您可以像下面的泛型函数一样使用Reflection 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);