c# - 卡住 linq IQueryable(就像 ToList().AsQueryable() 会做的那样)

标签 c# linq entity-framework odata

有没有办法卡住 IQueryable,以便在访问数据库时不会向查询添加额外的连接?例如,我可以执行 .ToList() 来卡住查询,但这会影响性能,因为我所做的任何过滤都在中间层进行,并且我没有从预过滤中获得任何性能提升在数据库服务器上过滤?


为清楚起见编辑:

我有一个 OData 服务,它返回一个 IQueryable,客户端可以根据需要过滤/排序/投影。我只是想阻止他们提取更多数据。我可以通过执行 ToList().AsQueryable() 来做到这一点,但这失去了 lazyLoading 的优势,并且失去了允许客户端过滤请求的全部目的。

我查看的一个选项是设置:EnableQueryAttribute.AllowedQueryOptions 以排除 Expand,但是即使我的初始查询已扩展,客户端仍然无法访问选择那些部分。

最佳答案

我假设您实际上有一个 IQueryable<T>而不是 IQueryable .

如果您不希望您的客户访问所有 IQueryable<T>方法,不要返回 IQueryable<T> .由于您希望他们只能过滤/排序/项目,因此创建一个包含 IQueryable<T> 的对象但只公开所需的方法,并使用它:

public interface IDataResult<T>
{
    IDataResult<T> FilterBy(Expression<Func<T, bool>> predicate);

    IDataResult<TResult> ProjectTo<TResult>(Expression<Func<T, TResult>> predicate);

    IDataResult<T> SortBy<TKey>(Expression<Func<T, TKey>> keySelector);

    IDataResult<T> SortByDescending<TKey>(Expression<Func<T, TKey>> keySelector);

    List<T> ToList();

    IEnumerable<T> AsEnumerable();
}

public class DataResult<T> : IDataResult<T>
{
    private IQueryable<T> Query { get; set; }

    public DataResult(IQueryable<T> originalQuery)
    {
        this.Query = originalQuery;
    }

    public IDataResult<T> FilterBy(Expression<Func<T, bool>> predicate)
    {
        return new DataResult<T>(this.Query.Where(predicate));
    }

    public IDataResult<T> SortBy<TKey>(Expression<Func<T, TKey>> keySelector)
    {
        return new DataResult<T>(this.Query.OrderBy(keySelector));
    }

    public IDataResult<T> SortByDescending<TKey>(Expression<Func<T, TKey>> keySelector)
    {
        return new DataResult<T>(this.Query.OrderByDescending(keySelector));
    }

    public IDataResult<TResult> ProjectTo<TResult>(Expression<Func<T, TResult>> predicate)
    {
        return new DataResult<TResult>(this.Query.Select(predicate));
    }

    public List<T> ToList()
    {
        return this.Query.ToList();
    }

    public IEnumerable<T> AsEnumerable()
    {
        return this.Query.AsEnumerable();
    }
} 

通过这种方式,您还可以防止 EF 和 DB 相关依赖项在您的应用程序中蔓延。 IQueryable<T> 上的任何更改方法将包含在此类中,而不是遍布各处。

关于c# - 卡住 linq IQueryable(就像 ToList().AsQueryable() 会做的那样),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30770017/

相关文章:

c# - 如何处理多个xml标准?

c# - 有什么方法可以优化这个 LINQ to Entities 查询吗?

c# - 将 EF CodeFirst 基类转换为继承类(使用 table-per-type)

c# - 包含不符合 CLS 的引用的程序集是否符合 CLS?

c# - 企业服务总线真实世界的使用或示例

c# - 通用对象缓存

LINQ to Objects .Distinct() 不提取不同的对象

c# - 如何在没有 app.conf 文件的情况下使用 EF Code-First?

c# - EntityFramework 使用另一个值更新实体?

c# - 使用 C# 代码检查默认邮件客户端