ToList()不适用于动态生成的where子句Asp.Net Core 我正在建立过滤管道。所以我有了从dbcontext检索iqueryable的方法,它看起来像以下内容:
public IEnumerable<Event> Filter(EventFilterModel filterModel)
{
_filterManager = new EventsSelectionPipeline();
_filterManager.Register(new EventTypeFilter(filterModel.EventTypes, _unitOfWork));
var events = _unitOfWork.DbContext.Events;
var filteredEvents = _filterManager.Process(events);
return filteredEvents.ToList();
}
处理方法:
public override IQueryable<Event> Process(IQueryable<Event> input)
{
foreach(var filter in _filters)
{
filter.Execute(input);
}
return input;
}
EventTypeFilter:
public class EventTypeFilter : IFilter<IQueryable<Event>>
{
private readonly IEnumerable<EnumEventType> _eventTypes;
private readonly IUnitOfWork<ApplicationContext> _unitOfWork;
public EventTypeFilter(IEnumerable<EnumEventType> eventTypes, IUnitOfWork<ApplicationContext> uow)
{
_eventTypes = eventTypes;
_unitOfWork = uow;
}
public IQueryable<Event> Execute(IQueryable<Event> input)
{
if (_eventTypes.Any())
{
BinaryExpression condition = null;
var expr = new List<Expression<Func<Event, bool>>>();
var parameter = Expression.Parameter(typeof(Event), "ev");
foreach(var eventType in _eventTypes)
{
var property = Expression.Property(parameter, "EventType");
var propType = ((PropertyInfo)property.Member).PropertyType;
var converter = TypeDescriptor.GetConverter(propType);
var propertyValue = eventType;
var constant = Expression.Constant(propertyValue);
var valueExpression = Expression.Convert(constant, propType);
var dynExpr = Expression.Equal(property, valueExpression);
condition = condition == null ? dynExpr : Expression.Or(condition, dynExpr);
}
if(condition != null)
{
var predicate = Expression.Lambda<Func<Event, bool>>(condition, parameter);
input = input.Where(predicate);
}
}
return input;
}
}
在IQueryable<Event> Process(IQueryable<Event> input)
方法中,执行以正确数量的元素执行iqueryable的返回(使用过滤),但是当我将iList应用于iQueryable时,它只是返回我的初始数据集而没有过滤。
答案 0 :(得分:1)
filter.Execute(input);
这可能应该是
input = filter.Execute(input);
否则,您的过滤器不会“粘住”。
答案 1 :(得分:1)
您必须记住过滤后的查询:
public override IQueryable<Event> Process(IQueryable<Event> input)
{
foreach(var filter in _filters)
{
input = filter.Execute(input);
}
return input;
}
如果要避免将结果分配回原始查询,还可以通过引用传递查询:
public void Execute(ref IQueryable<Event> input)
{
if (_eventTypes.Any())
{
//...
if(condition != null)
{
var predicate = Expression.Lambda<Func<Event, bool>>(condition, parameter);
input = input.Where(predicate);
}
}
}
//...
public override IQueryable<Event> Process(IQueryable<Event> input)
{
foreach(var filter in _filters)
{
filter.Execute(ref input);
}
return input;
}
这将允许以更“自然”的方式应用过滤器,而第一个选项则更为灵活,因为它可以让您保留初始查询。