我有一个带有以下签名的方法,它返回一个C#表达式
Expression<Func<T, bool>> GetExpression<T>(IList<Filter> filters)
然后使用Dynamic LINQ
的以下代码using (TestContext tEntities = new TestContext())
{
var filterExp = Exp.ExpressionBuilder.GetExpression<Client>(filters);
var filteredCollection = tEntities.Client.Where(filterExp);
IQueryable<Client> queryResult;
if (filterExp == null)
queryResult = tEntities.Client;
else
queryResult = tEntities.Client.Where(filterExp);
}
这是一个简单的场景。 我的查询有时多50行。我想避免使用相同的代码两次,只使用where子句进行区别。
有谁知道我是否实现了不同的目标?
from product in context.Product.Where(deleg)
.Include(x => x.Type)
.Include(x => x.Category)
.Include(x => x.WareHouse)
.Include(x => x.Photos)
join f in context.Favorite on product.Id equals f.ProductFid into fg
from fgi in fg.Where(f => f.UserFid == userId).DefaultIfEmpty()
orderby product.Id descending
select new ProductngDto()
{
ProductItem = product,
FavoriteId = fgi != null ? fgi.Id : (long?)null
}).Skip(page * pageSize).Take(pageSize);
提前致谢
答案 0 :(得分:2)
关于IQueryable<T>
和IEnumerable<T>
的好处之一是它们如此抽象,您可以轻松地将它们链接在一起。一种解决方案可能是像这样构建代码:
using (TestContext tEntities = new TestContext())
{
var filterExp = Exp.ExpressionBuilder.GetExpression<Client>(filters);
var filteredCollection = tEntities.Client.Where(filterExp);
IQueryable<Client> queryResult = tEntities.Client;
if (filterExp != null)
{
queryResult = queryResult.Where(filterExp);
}
//do something else with queryResult
}
通过这种方式,您可以继续使用queryResult
,而无需了解甚至关心filterExp
是否已应用。
对于第二个例子,将它改组可能看起来像这样:
var query = from p in context.Product
.Include(x => x.Type)
.Include(x => x.Category)
.Include(x => x.WareHouse)
.Include(x => x.Photos);
if (deleg != null)
{
query = query.Where(deleg);
}
query = from product in query
join f in context.Favorite on product.Id equals f.ProductFid into fg
from fgi in fg.Where(f => f.UserFid == userId).DefaultIfEmpty();
orderby product.Id descending
select new ProductngDto()
{
ProductItem = product,
FavoriteId = fgi != null ? fgi.Id : (long?)null
}).Skip(page * pageSize).Take(pageSize);
你有另一个选择,就是检查filterExp
是否为空,并为其指定一个“始终为真”的lambda。
如果您控制GetExpression<T>
方法,则可以将其添加到最后一步。如果你不控制它,你可以在使用它的结果的方法中进行空检查。
这将使您的代码看起来更清晰,但是由于必须始终评估lambda,因此权衡很小。
根据表达式的输入方式,这可能很简单:
if (filterExp == null)
{
filterExp = (_) => true;
}