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.
我只是花了一些时间来寻找如何从一个方法 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.