【问题标题】:Return IQueryable<T> from my method? Is it the right way to do it?从我的方法中返回 IQueryable<T>?这是正确的方法吗?
【发布时间】:2015-04-25 10:36:56
【问题描述】:

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

这是我的存储库类:

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 是否正确?

感谢您的帮助! 巴斯蒂安

【问题讨论】:

  • 我宁愿返回IEnumerable&lt;Car&gt;而不是IQueryable
  • @AlexSikilinda IQueryable 是数据库的better choice。但是我一般不赞成这一点,我认为返回 IQueryables 的存储库价值较低(也可以直接使用 EF/LtSql 等 linq 提供程序,并且您的抽象将在您不期望的宫殿中泄漏[例如,在以 EF 为例,是否清楚跟踪哪些数据?)。
  • 这样就好了。将责任留给将与存储库交互的 Dal 层。然后在 dal 层中调用 ToList,当您完成整个查询构造时。

标签: c# linq expression iqueryable


【解决方案1】:

就目前而言,这没有任何意义。如果要使用Queryable 方法对数据库进行远程查询,则必须使用表达式树。使用Compile 会将树转换为破坏此机会的委托。

_entities 必须是 IQueryable&lt;T&gt; 才能定位 Queryable 方法。

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

【讨论】:

    【解决方案2】:

    原因

    var query = _entities.Where(predicate);
    

    失败是因为_entities 只实现了IEnumerable&lt;Car&gt;,而不是IQueryable&lt;Car&gt;IEnumerable&lt;T&gt;Enumerable.Where 扩展方法采用 Func&lt;T, bool&gt;IQueryable&lt;T&gt;Queryable.Where 扩展方法采用 Expression&lt;Func&lt;T, bool&gt;&gt;

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-25
      • 1970-01-01
      • 2019-09-05
      • 1970-01-01
      相关资源
      最近更新 更多