如何为链接到实体应用动态过滤器并在服务器端执行它们
本文关键字:服务器端 执行 过滤器 动态 链接 应用 实体 | 更新日期: 2023-09-27 18:14:45
我想写一个类,它基本上提供了一个条目列表。这些条目既可以从数据库中读取,也可以在应用程序生存期内生成。该类应该提供一种过滤这些条目的方法。是否有可能实现两个源只需要一个过滤器的过滤器?
例如:interface IFilter
{
bool Filter(ILogEntry entry);
}
对于带有IEnumerable的LINQ,将其应用为动态过滤器没有问题。
IEnumerable<IFilter> filters;
IEnumerable<ILogEntry> entries;
foreach(var filter in filters)
entries = entries.Where(p => filter.Filter(p));
但是对于Linq-To-Sql,有两个问题我没有解决方案:
- 如何将上下文提供的LogEntry转换为ILogEntry?
- 我如何确保查询将在服务器上执行而不是在本地执行?
下面的代码将在服务器上实际执行过滤器,这对我来说似乎有点奇怪。但是,如果我在这个以ILogEntry(由LogEntry实现)作为参数的查询中使用filter,则过滤器将在客户端应用:
entities.Logs
.Select(p => new LogEntry() { Message = p.Message })
.Where(p => p.Message == "132");
是否有一种方法可以为iccollection和IQueryable编写过滤器,并确保IQueryable过滤器将在SQL-Server上执行?
应用该服务器端的唯一方法是将组合为表达式树,例如:
interface IFilter {
public Expression<Func<ILogEntry, bool>> GetPredicate();
}
...
IQueryable<ILogEntry> entries = ...
foreach(var filter in filters) {
entries = entries.Where(filter.GetPredicate());
}
这就要求实现如下:
public Expression<Func<ILogEntry, bool>> GetPredicate() {
return x => x.SomeField == 25;
}
注意:如果你有一个内存中的数据缺口,你可以通过使用.AsQueryable()
从IEnumerable<T>
切换到IQueryable<T>
,这允许它在本地使用表达式树