在LINQ中构建动态查询谓词
#dotnet #database #orm #csharp

我创建了一个Nuget软件包Linq.Extension.PredicateBuilder,可以通过在属性组合中应用过滤来解决过滤器收集中的复杂性。

概述

要使方案具体,让我们假设我们的对象被声明如下:

public class Post
  {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Description { get; set; }
        public bool IsPublished { get; set; }
        public DateTime PublishedAt { get; set; }
        public int TotalViews { get; set; }
        public int TotalComments { get; set; }
  }

现在假设我们有这样的帖子集合(这仅是出于解释目的,在现实生活中,您会从数据库中获得更大的收藏

var posts = new List<Post>
            {
                new Post {Id = 1, Name = "post1" , Description = "post1 description", IsPublished = true, PublishedAt = DateTime.Now, TotalViews = 50, TotalComments = 4},
                new Post {Id = 2, Name = "post2" , Description = "post2 description", IsPublished = false, PublishedAt = DateTime.Now.AddDays(-3), TotalViews = 10, TotalComments = 1},
                new Post {Id = 3, Name = "post3" , Description = "post3 description", IsPublished = true, PublishedAt = DateTime.Now.AddDays(-8), TotalViews = 120, TotalComments = 8},
                new Post {Id = 4, Name = "post4" , Description = "post4 description", IsPublished = true, PublishedAt = DateTime.Now.AddDays(-1), TotalViews = 40, TotalComments = 5},
                new Post {Id = 5, Name = "post5" , Description = "post5 description", IsPublished = true, PublishedAt = DateTime.Now, TotalViews = 0, TotalComments = 0},
                new Post {Id = 6, Name = "post6" , Description = "post6 description", IsPublished = true, PublishedAt = DateTime.Now.AddDays(-10), TotalViews = 150, TotalComments = 10},
                new Post {Id = 7, Name = "post7" , Description = "post7 description", IsPublished = false, PublishedAt = DateTime.Now, TotalViews = 0, TotalComments = 0},
                new Post {Id = 8, Name = "post8" , Description = "post8 description", IsPublished = true, PublishedAt = DateTime.Now.AddDays(-20), TotalViews = 250, TotalComments = 15},

            };

假设我们要允许用户过滤任何属性或任何属性组合的集合,一种方法是为每个属性和每个属性组合都具有一个函数,例如:

public IList<Post> FilterByName(string  name)
{
    return  posts.Where(p => p.Name == name).ToList();
}

public  IList<posts> FilterByDescription(string  description)
{
    return  posts.Where(p => p.Description.Contains(description)).ToList();
}

public  IList<posts> FilterByTotalViewsGreaterOrEqual(int totalViews)
{
    return  posts.Where(p => p.TotalViews >= totalViews).ToList();
}

您可以看到,这变得非常乏味,因为涵盖所有可能组合的功能数量很大。

过滤集合的另一种方法,这更方便,更整洁是动态构建表达树,然后将其传递给Where子句进行过滤,以便Linq.Extension.PredicateBuilder

安装

dotnet add package Linq.Extension.PredicateBuilder

用法

using Linq.Extension.PredicateBuilder;

namespace ConsoleAppTest
{
    internal class Program
    {
        static void Main(string[] args)
        {
            var searchFilters = new List<SearchFilter> {
                new SearchFilter{PropertyName = "Name", Operation = OperatorComparer.BeginsWith, Value = "post" },
                new SearchFilter{PropertyName = "IsPublished", Operation = OperatorComparer.Equal, Value = true },
                new SearchFilter{PropertyName = "TotalViews", Operation = OperatorComparer.GreaterOrEqual, Value = 150 },
            };

            var predicate = PredicateBuilder.Compile<Post>(searchFilters);

            var filteredPostsResult = new Post().GetPosts().Where(predicate).ToList();
        }
    }
}

那集#happycodingð