c# - 使用动态 LINQ 的空表达式

标签 c# linq

我有一个具有以下签名的方法,该方法返回 C# 表达式

Expression<Func<T, bool>> GetExpression<T>(IList<Filter> filters)

然后是使用动态 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);

提前致谢

最佳答案

关于 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为 null 并为其分配一个“始终为真”的 lambda。 如果你控制GetExpression<T>方法,您可以将其添加到那里作为最后一步。如果您不控制它,您可以在使用其结果的方法中进行空检查。

这将使您的代码看起来更简洁,但代价是必须始终评估 lambda,从而对性能造成一点影响。

根据表达式的输入方式,这可能很简单:

if (filterExp == null)
{
    filterExp = (_) => true;
}

关于c# - 使用动态 LINQ 的空表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41320543/

相关文章:

c# - 运行 c# 编译代码时的 Windows 调度程序功能

linq - 关于 IQueryable<T>.GetEnumerator 的一些令人困惑的事情

c# - 如何为我的应用程序构建搜索机制?

c# - 无法加载文件或程序集 'WebGrease' 它的依赖项之一。找到的程序集的 list 定义与程序集引用不匹配

c# - 获取 WrapPanel 中的行数?

c# - 从 c# 调用 javascript 函数来替换 div

c# - 为什么使用此 Linq to Sql 方法会出现 InvalidOperationException?

c# - LINQ 方法通过一个函数加入一个系列中的每 n 个元素,然后将这些结果重新聚合到一个新列表中?

c# - 将多个字符串拆分为 C# 中的对象列表

c# - 设计或代码模式以从函数返回多个可选值