Return IQueryable<T> 来自我的方法?这是正确的方法吗?

Return IQueryable<T> from my method? Is it the right way to do it?

我只是花了一些时间来寻找如何从一个方法 return IQueryable...我仍然想知道这是否是正确的方法。

这是我的存储库 class:

public class CarRepository : ICarRepository
{
    // Fake entities
    private IList<Car> _entities = new List<Car>()
    {
        new Car() { Brand = "Lamborghini", Name = "Huracán"},
        new Car() { Brand = "BMW", Name = "X6" }
    };

    // Allows deferred execution/further refinement
    public IQueryable<Car> FindByQueryable(Expression<Func<Car, bool>> predicate)
    {
        var query = _entities.Where(predicate.Compile()).AsQueryable();
        return query;
    }

    // Returning an IList or IEnumerable
    public IList<Car> FindBy(Expression<Func<Car, bool>> predicate)
    {
        return _entities.Where(predicate.Compile()).ToList();
    }
}

起初我认为类似的东西应该可以工作,但它没有编译:

    public IQueryable<Car> FindByQueryable(Expression<Func<Car, bool>> predicate)
    {
        var query = _entities.Where(predicate);
        return query;
    }

我对 predicate.Compile() 和 .AsQueryable 是否正确?

感谢您的帮助! 巴斯蒂安

就目前而言,这毫无意义。如果要使用 Queryable 方法远程查询数据库,则必须使用表达式树。使用 Compile 将树转换为委托,从而破坏了这个机会。

_entities 必须是 IQueryable<T> 才能定位 Queryable 方法。

AsQueryable 是一种代码味道,通常表示上述错误。这是一个假的可查询。它在内存中(除非源确实是 IQueryable;然后它会进行转换)。

原因

var query = _entities.Where(predicate);

失败是因为_entities只实现了IEnumerable<Car>,而不是IQueryable<Car>IQueryable<T>Enumerable.Where extension method for IEnumerable<T> takes a Func<T, bool>. The Queryable.Where 扩展方法采用 Expression<Func<T, bool>>.

您可以将 AsQueryable() 向上移动一点,而不是手动编译表达式树:

var query = _entities.AsQueryable().Where(predicate);

正如 usr 的回答正确指出的那样,这通常没有意义,因为它将使用本地过滤,而不是任何服务器端过滤。但是,在某些情况下确实有意义的例外情况,您的情况可能就是这样一个例外:如果您有多个 ICarRepository 的实现,一些是本地的,一些是远程的,那么按照您的方式进行可能是非常有意义的正在做。您不希望 ICarRepository 的用户不得不处理是使用委托还是表达式树的问题:用户应该只使用表达式树,然后您的 CarRepository 可以将这些表达式树传递给一些查询提供程序,然后该查询提供程序可以选择是将它们编译为委托,还是将它们翻译成其他语言,例如 SQL.