本文介绍了冻结LINQ的IQueryable(作为了ToList()。AsQueryable已()会做)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有没有办法冻结了的IQueryable 所以没有额外的连接访问数据库时,将添加到查询?例如,我可以做一个 .ToList()冻结查询,但有性能影响,因为我做的任何过滤是中间层上,我没有从预过滤的性能提升数据库服务器

Is there a way to freeze an IQueryable so that no additional joins will be added to the query when hitting the database? For example, I could do a .ToList() to freeze the query, but that has performance impacts because any filtering I do is on the middle layer and I don't have any performance gains from pre-filtering on the db server?

修改为清楚起见上:

我有一个返回的IQueryable 客户端可以过滤/排序/按需要项目OData服务。我只是想阻止他们拉更多的数据出来。我能做到这一点做了ToList()。AsQueryable已(),但失去了惰性加载的优势,有了它,可以让客户端过滤请求的全部目的

I have an OData service which returns an IQueryable that the client can filter/sort/project as needed. I just want to prevent them from pulling more data out. I could do that by doing ToList().AsQueryable(), but that loses the advantage of lazyLoading, and with it, the whole purpose of allowing the client to filter the request.

这是我看着一个方案是设置: EnableQueryAttribute.AllowedQueryOptions 排除展开,但即使我的初始查询有所扩大,客户端仍然选择那些部分预防。

One option that I looked at was to set: EnableQueryAttribute.AllowedQueryOptions to exclude Expand, however even if my initial Query had been expanded, the client is still prevented from selecting those parts.

推荐答案

林假设你确实有一个的IQueryable< T> ,而不是的IQueryable


如果你不想让你有客户端的所有访问的IQueryable< T> 方法,不返回的IQueryable< ; T> 。既然你想让他们只能够过滤器/排序/项目,创建一个对象巫婆包含的IQueryable< T> ,但只公开所需的方法和使用:

Im assuming that you actually have an IQueryable<T> instead of a IQueryable.

If you don't want your client having access to all IQueryable<T> methods, don't return an IQueryable<T>. Since you want them to be able to only filter/sort/project, create a object witch contains an IQueryable<T> but only expose the desired methods, and use that:

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相关的依赖性您的应用程序攀升。 T> 方法将被包含的传播,而不是所有的地方这个类中,

That way you can also prevent EF and DB related dependencies creeping up on your application. Any change on IQueryable<T> methods will be contained within this class, instead of spread all over the place.

这篇关于冻结LINQ的IQueryable(作为了ToList()。AsQueryable已()会做)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-24 11:31