如何使 IQueryable 可重用和可链接?

How to make IQueryable reusable and chainable?

我想我在这里有点困惑。

我的 EF 项目有一些存储库和服务。我希望能够使用 IQueryable 对我的任何模型进行分页。

我的存储库包含一个方法 returns IQueryable:

public IQueryable<TEntity> GetQuery()
{
    return EntitySet;
}

我还有一个查询对象,我打算将其用于可重用查询。是这样的:

public static class CarQuery 
{
    public static IQueryable<Car> RegisteredCars(this IQueryable<car> car, int userId)
    {
        return car.Where(r => r.RegisteredUser.UserId == userId);
    }

    public static IQueryable<car> WithStockAvailability(this IQueryable<car> car, bool isAvailable)
    {
        return car.Where(r => r.IsInStock == isAvailable);
    }
}

我正在我的服务层中使用它,如下所示:

public IEnumerable<Car> GetUserRegisteredCarsInStock(int userId, int? pageNumber, int? pageSize)
{
    var query = _repository.GetQuery(); 

    query = query.RegisteredCars(userId);
    query = query.WithStockAvailability(true);


    if (pageSize.HasValue && pageNumber.HasValue)
    {
        return .OrderByDescending(r => r.carId) // for some reason if I don't have the order, the query fails
                .Skip(pageNumber.Value * pageSize.Value)
                .Take(pageSize.Value);
    }

    return query.ToList();
}

但我认为我这样做不对。特别是这一行:

    query = query.RegisteredCars(userId);
    query = query.WithStockAvailability(true);

如何使它看起来像这样:

    query.RegisteredCars(userId)
       .WithStockAvailability(true)
       .Page(pageNumber, pageSize);

谢谢

只要您创建了 Page 扩展方法,该行应该可以工作。

您可以修改 Page 方法以包含这样的 order by 子句:

 public static IQueryable<T> Page<T, TKey>(this IQueryable<T> source,
     Expression<Func<T, TKey>> orderExpression, 
     int pageNumber, int pageSize)
 {
    return source.OrderBy(orderExpression)
                 .Skip(pageNumber * pageSize)
                  .Take(pageSize);
 }

你这样调用方法:

query = query.Page(r => r.CarId, pageNumber, pageSize);

您已经完成了前两个。

IQueryable<car> query = _repository.GetQuery()
                                   .RegisteredCars(userId)
                                   .WithStockAvailability(true);

Paging 只需要一个通用的扩展函数,它需要一个 ordered query:

public static IQueryable<T> Paging(this IOrderedQueryable<T> query, 
                                   int? pageSize,
                                   int? pageNumber)
{
    if (pageSize.HasValue && pageNumber.HasValue)
    {
        return query.Skip(pageNumber.Value * pageSize.Value)
                    .Take(pageSize.Value);
    }

    return query;
}

所以现在您可以将整个事情链接起来:

IQueryable<car> query = _repository.GetQuery()
                                   .RegisteredCars(userId)
                                   .WithStockAvailability(true)
                                   .OrderByDescending(c => c.carId)
                                   .Paging(pageSize, pageNumber);