具有动态LINQ的空表达式

时间:2016-12-25 10:57:23

标签: c# linq

我有一个带有以下签名的方法,它返回一个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);

提前致谢

1 个答案:

答案 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;
}