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);