如何保持lambda表达式的引用,该表达式将稍后传递给OrderBy或LoadWith函数

本文关键字:表达式 OrderBy 函数 LoadWith lambda 何保持 引用 | 更新日期: 2023-09-27 18:17:22

我正在尝试创建访问DB的一般方法。这将包含如下参数:页面索引、每页显示的项目数、排序选项、加载选项等。

...
public IQuerable<T> GetAll(int pageIndex, int itemsToDisplayPerPage, System.Linq.Expressions.Expression<Func<T,object>>[] orderBy, System.Linq.Expressions.Expression<Func<T,object>>[] loadOptions)
{
  DataContext dc = null;
  IQuerable<T> result = null;
  // Make some initalizations
  ...
  foreach(var item in orderBy)
  {
    result = result.OrderBy(item);
  }
  System.Data.Linq.DataLoadOptions loadOptions = new System.Data.Linq.DataLoadOptions();
  foreach(var item in loadOptions)
  {
    loadOptions.LoadWith(item);
  }
  ...
}
...

问题是System.Linq.Expressions.Expression< Func< T,object > >类型并不是一个很好的lambda表达式的通用表示,对于上面的两个例子来说,它都是传递的。

On排序将崩溃,因为对象类型对排序没有任何意义。也在loadWith将不工作。所以我不知道该如何处理这个问题。有什么建议吗?谢谢你。

如何保持lambda表达式的引用,该表达式将稍后传递给OrderBy或LoadWith函数

不确定LoadWith,因为我们正在使用linq到实体,但我们成功地使orderby在存储库Get方法中工作。客户端代码如下所示:

var results = _repository.GetAll(
    new GetAllCriteria()
        .OrderBy(x => x.Property1)
        .OrderBy(x => x.Property2)
);

我们还没有在存储库方法中使用泛型,这可能会在将来的重构中出现。但是标准实现看起来是这样的:

public class GetAllCriteria
{
    public Dictionary<Expression<Func<CustomType, object>>, bool> ToBeOrderedBy 
    { 
        get; private set;
    }
    public GetAllCriteria OrderBy(
        Expression<Func<CustomType, object>> expression)
    {
        return OrderBy(expression, true);
    }
    public GetAllCriteria OrderByDescending(
        Expression<Func<CustomType, object>> expression)
    {
        return OrderBy(expression, false);
    }
    private GetAllCriteria OrderBy(
        Expression<Func<CustomType, object>> expression, bool isAscending)
    {
        if (expression != null)
        {
            if (ToBeOrderedBy == null)
                ToBeOrderedBy = new Dictionary<Expression<Func<CustomType, object>>, bool>();
            ToBeOrderedBy.Add(expression, isAscending);
        }
        return this;
    }   
}

然后,存储库命令如下:

public Collection<CustomType> GetAll(GetAllCriteria criteria)
{
    var query = dbContext.CustomTypes.AsQueryable();
    // some code
    // apply order by
    if (criteria.ToBeOrderedBy != null && criteria.ToBeOrderedBy.Count > 0)
    {
        var firstOrderBy = criteria.ToBeOrderedBy.First();
        query = firstOrderBy.Value
            ? query.OrderBy(firstOrderBy.Key)
            : query.OrderByDescending(firstOrderBy.Key);
        query = criteria.ToBeOrderedBy.Skip(1).Aggregate(query, 
            (lastOrderBy, nextOrderBy) => nextOrderBy.Value
            ? ((IOrderedQueryable<CustomType>)lastOrderBy)
                .ThenBy(nextOrderBy.Key)
            : ((IOrderedQueryable<CustomType>)lastOrderBy)
                .ThenByDescending(nextOrderBy.Key));
    }
    // some more code
    var results = query.ToList();
    return results;
}

如果这适用于linq到实体,我想它应该适用于linq到sql。