【问题标题】:C# filter based on request api基于请求 api 的 C# 过滤器
【发布时间】:2020-12-05 00:35:16
【问题描述】:

我正在尝试过滤显示在我的应用程序中的帖子。一切都按预期进行,但我有一个小问题。用户可以选择他所遵循的教育和职业。如何根据获得的数组进行过滤?我试过这样的东西,但感觉很难看。如果我在我的 Filter 类中设置更多的数组,比如 Language[].. 它会变得更加混乱。我可以做点简单的事吗?

public class Filter
{
    public string[] Education { get; set; }

    public string[] Profession { get; set; }
    public int PageIndex { get; set; }

}

示例请求:

public PaginatedResults<Post> FilterPosts(Filter filter)
{

// Both Education and Profession arrays are empty, we just return all the posts
    if(filter.Profession.Any(prof => prof == null) && filter.Education.Any(study => study == null)) {
        var posts1 = _dbContext.Posts.AsEnumerable();
        return _searchService.Pagination<Post>(posts1, filter.PageIndex);
    }
    else 
    {
        // Can this be simplified? Sometimes the Education array is empty and sometimes Profession array. User can choose
        IEnumerable<Post> posts = null;
        if(filter.Profession.Any(prof => prof == null)) 
        {
            posts = _dbContext.Posts.Where(post => filter.Education.Contains(post.Education)).AsEnumerable();
        }
        else if(filter.Education.Any(study => study == null)) 
        {
            posts = _dbContext.Posts.Where(post => filter.Profession.Contains(post.Profession)).AsEnumerable();
        }
        else 
        {
            posts = _dbContext.Posts.Where(post => filter.Profession.Contains(post.Profession) && filter.Education.Contains(post.Education)).AsEnumerable();
        }
        return _searchService.Pagination<Post>(posts, filter.PageIndex);
    }
}

【问题讨论】:

    标签: c# .net asp.net-web-api asp.net-core-webapi


    【解决方案1】:

    可能有很多方法可以解决这个问题。假设您想保持您的方法(我认为这是完全有效的),您可以尝试以下步骤:

    利用IQueryable

    假设您使用实体框架,我相信_dbContext.Posts 已经实现了IQueryable。由于 LINQ 不会立即执行,我们可以在枚举集合之前依次构建过滤条件:

    posts = _dbContext.Posts.Where(post => filter.Education.Contains(post.Education) && filter.Education.Contains(post.Profession)).AsEnumerable();
    
    // since you are implementing `AND` semantics for your filters, is easy to break down into series of `.Where()` calls
    posts = _dbContext.Posts.Where(post => filter.Education.Contains(post.Education))
                            .Where(post => filter.Education.Contains(post.Profession))
                            .AsEnumerable(); // this should filter Posts by Education AND Profession as well as represent the result as IEnumerable. Should be functionally identical to the first statement
    

    反转布尔条件并检查过滤器是否

    这将允许您仅在需要时添加.Where 过滤器:

    if (filter.Profession.Any()) // if Profession has elements
    {
        posts = posts.Where(post => filter.Profession.Contains(post.Profession)); // apply respective filter to posts, you may want to ensure you only compare against meaningful search terms by appplying `.Where(i => !string.IsNullOrWhiteSpace(i))` to it
    }
    if (filter.Education.Any()) // if Education has elements
    {
        posts = posts.Where(post => filter.Education.Contains(post.Education)).AsEnumerable(); // apply respective filter to posts          
    }
    

    然后,把它们放在一起

    public PaginatedResults<Post> FilterPosts(Filter filter)
    {
        IQueryable<Post> posts = _dbContext.Posts;
        if (filter.Profession.Any()) posts = posts.Where(post => filter.Profession.Contains(post.Profession));
    
        if (filter.Education.Any()) posts = posts.Where(post => filter.Education.Contains(post.Education));
    
        return _searchService.Pagination<Post>(posts.AsEnumerable(), filter.PageIndex); 
    }
    

    【讨论】:

    • 这在原则和建议上似乎是正确的,但我怀疑IEnumerable&lt;Post&gt; posts = _dbContext.Posts; 的使用,这可能会产生无法预料的影响。
    • @AluanHaddad 哦,这是复制粘贴神器。应该是IQueryablevar。有机会我会更新的
    • 我真的很喜欢这种方法,但是有一个问题我没有正确解释。当我调用我的 api 时:api/posts/filter?profession=ICT&amp;education=&amp;pageIndex=1 教育或专业可以为空。这就是为什么我发布上面的图片。例如,education 为空:filter.Education[0] 变为 null,filter.Education.Any() 变为 true。 .Where(post =&gt; filter.Education.Contains(post.Education)) 变成 0 个帖子,因为我没有任何带有 null 的教育。我该如何解决这个问题?
    • ``` if(filter.Profession.Any(prof => prof != null)) { posts = posts.Where(post => filter.Profession.Contains(post.Profession)); }```哦,我做到了,它奏效了。感谢您提供的帮助。我现在了解如何在不立即执行的情况下构建查询:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-09-17
    • 2020-07-16
    • 2014-06-15
    • 2022-08-15
    • 1970-01-01
    • 1970-01-01
    • 2023-03-24
    相关资源
    最近更新 更多