使用Entity Framework Core构建动态查询 - “逐步”构建查询

4
我正在尝试创建一个类来执行动态过滤,取决于我将发送到其“filter”方法的参数,但我在构建查询时遇到了一些困难。
通过我的下面的代码更容易解释,我只是在尝试根据输入应用一些过滤器:
public class PeopleManager : Controller
    {
        private readonly MyPeopleContext _context;
        public PeopleManager(PeopleContext context)
        {
            _context = context;
        }

        public IEnumerable<Person> filter (int? id, string name, int? age)
        {
            var peoplequery = _context.People;
            if(id!=null)
            {
               peoplequery = peoplequery .Where(p => p.Id.Equals(id));
            }

            if(name!="")
            {
               peoplequery = peoplequery .Where(p => p.Name.Contains(name));
            }

            if(age!=null)
            {
               peoplequery  = peoplequery .Where(p => p.Age.Equals(age));
            }

            return peoplequery;
        }
    }

显然,我的代码没有起作用,根据我找到的这个问题:

无法将类型'System.Linq.IQueryable'隐式转换为类型'System.Data.Entity.DbSet'

我已经成功地编辑了我的代码如下:

public IEnumerable<Person> filter (int? id, string name, int? age)
            {
                var people = _context.People;

                var peoplequery = from p in people select people;

                if(id!=null)
                {
                   peoplequery = peoplequery .Where(p => p.Id.Equals(id));
                }

                if(name!="")
                {
                   peoplequery = peoplequery .Where(p => p.Name.Contains(name));
                }

                if(age!=null)
                {
                   peoplequery  = peoplequery .Where(p => p.Age.Equals(age));
                }

                return peoplequery;
            }

但是这样做,我无法在我的lambda表达式中访问人的属性,例如id、name等。

我该如何构建这个条件查询而没有任何错误?


3
请移除 if 语句块内的 var。目前代码不能编译通过。同时在开头使用简单的 var peoplequery = _context.People.AsQueryable(); - Ivan Stoev
1
然后应用AsQueryable(),就完成了 :) 我的意思是,不要使用from p in ... - Ivan Stoev
1
没错。和 IQueryable<Person> people = _context.People; 或者 var people = from p in _context.People select p;(注意是 select p 而不是 people)一样。但是 AsQueryable() 更简短。 - Ivan Stoev
1
如果您查看接口的声明,您会发现 IQueryable<T> 继承了 IEnumerable<T>,所以没有问题(从面向对象编程的角度来看,queryable enumerable)。 - Ivan Stoev
2
var peoplequery = _context.People; 更改为 IQueryable<Person> peoplequery = _context.People; 应该可以解决这个问题。 - Marc Gravell
显示剩余3条评论
1个回答

4
我猜您想要类似这样的东西:

我猜您想要类似这样的东西:

public class PeopleController : Controller
{
    private readonly MyPeopleContext _context;

    public PeopleManager(PeopleContext context)
    {
        _context = context;
    }

    public IEnumerable<Person> Filter (int? id, string name, int? age)
    {
        var peoplequery = _context.People.AsQueryable();
        if(id.HasValue)
        {
           peoplequery = peoplequery.Where(p => p.Id == id.Value);
        }
        if(!string.IsNullOrEmpty(name))
        {
           peoplequery = peoplequery.Where(p => p.Name.Contains(name));
        }
        if(age.HasValue)
        {
           peoplequery = peoplequery.Where(p => p.Age == age.Value);
        }

        return peoplequery.ToArray();
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接