Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 应用IEnumerable<';T>;。IQueryable上的订购人<';T>;_C#_Entity Framework_Linq_Expression_Ienumerable - Fatal编程技术网

C# 应用IEnumerable<';T>;。IQueryable上的订购人<';T>;

C# 应用IEnumerable<';T>;。IQueryable上的订购人<';T>;,c#,entity-framework,linq,expression,ienumerable,C#,Entity Framework,Linq,Expression,Ienumerable,我在我的存储库中使用了一个自定义类型,它可以帮助我显式地表示查询选项,例如排序、分页等 最初,界面如下所示: public class IQueryAction<TEntity> { IQueryable<TEntity> ApplyTo(IQueryable<T> entitity); } public class SortingAction<TEntity, TSortKey> : IQueryAction<TEntity>

我在我的存储库中使用了一个自定义类型,它可以帮助我显式地表示查询选项,例如排序、分页等

最初,界面如下所示:

public class IQueryAction<TEntity> {
    IQueryable<TEntity> ApplyTo(IQueryable<T> entitity);
}
public class SortingAction<TEntity, TSortKey> : IQueryAction<TEntity>
{
    public Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> SortAction { get; }

    public SortingAction(Expression<Func<TEntity, TSortKey>> sortExpression) {
        SortAction = q => q.OrderBy(sortExpression);
    }

    public IQueryable<TEntity> ApplyTo(IQueryable<TEntity> query) {
        return SortAction(query);
    }

}
这是否会导致在IQueryable出现时,排序操作在内存中而不是在查询提供程序上运行

是的,因为您将绑定到在内存中进行排序的
可枚举
扩展方法。在这一点上,底层提供者是什么并不重要;
Enumerable
扩展方法将枚举底层集合并在内存中对其进行“排序”

根据
IEnumerable
的基本类型,我可以做些什么来适应这两种情况,在内存中排序和在查询提供程序上排序

在调用方法之前,客户端可以调用
ToQueryable()
。如果基础集合已经是一个
IQueryable
,则输入只是强制转换;否则,将适配器放置在
IEnumerable
的顶部,以使
IQueryable
方法适应
IEnumerable
方法

我能做些什么来适应这两者,在内存中排序和在查询中排序 提供者

保持
IQueryAction
不变,并使用扩展名将
IEnumerable
转换为
IQueryable

var list = new List<YourEntity> { /* ... */ };
var queryableList = list.AsQueryable();

sortingAction.ApplyTo(queryableList);
var list=新列表{/*…*/};
var queryableList=list.AsQueryable();
sortingAction.ApplyTo(查询列表);

最终,这将对内存序列(如集合)进行内存内排序,并发送对数据库的查询以查找“真正”的查询项。

是的,如果使用
IEnumerable
方法,将导致在内存中进行排序。您可以使用
AsQueryable
IEnumerable
转换为
IQueryable
,并改用表达式树方法。有什么方法可以绕过它吗?由于
IQueryableWell的
.OrderBy()
实现要求使用表达式而不是委托。编译器可以(并且将)根据用例将lambda编译成两种类型。您可以轻松地从一个转换为另一个。也许我不明白你想做什么-你能添加一个你希望它如何工作的非工作示例吗?提供了使用示例。您可以看到,我无法使用现有接口,因为数据源中的结果集不支持
IQueryable
)。不,我不能轻易地将委托转换为表达式。。我可以,但我的表达式只是包装了一个委托,查询提供程序通常不知道这是什么:看来这是唯一的选择。我想改变/避免这一点,因为有了这个选项,我将不可避免地泄露信息。事实上,问题比你想象的更严重。有一种观点认为,公共接口中的
IQueryable
是邪恶的,因为
IQueryable
不能保证应用的方法不会在运行时抛出异常。例如,EF对类型有限制,可以在查询中使用,而在内存提供程序中则没有。从体系结构的角度来看,必须避免基于
IQueryable
的存储库,存储库必须提供预定义排序、排序、投影等方法。但IRL它会导致另一种问题(存储库代码增长非常快)。是的,我知道。我总是尽量避免使用上帝般的界面,但绝对不是不惜一切代价。例如,对于高级报告应用程序,我只是尝试充分保护API,以便客户端无法在我的存储提供商上执行某些不可能的操作。但是实现每一个组合、过滤和查询只是为了拥有99%的IQueryable
var list = new List<YourEntity> { /* ... */ };
var queryableList = list.AsQueryable();

sortingAction.ApplyTo(queryableList);